diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml index fa4decf0..ceed61f1 100644 --- a/.github/workflows/pkgdown.yaml +++ b/.github/workflows/pkgdown.yaml @@ -1,8 +1,11 @@ # Automatically rebuilds pkgdown website any time master branch is updated. +# Also builds pkgdown on "gh-pages-test" on commits to pull requests. # Based on . +# Conditional based on . on: push: branches: master + pull_request: name: pkgdown @@ -56,18 +59,32 @@ jobs: install.packages("pkgdown") shell: Rscript {0} - - name: Check Whitney availability + - name: Check Whitney availability in R run: | - message(paste(sysfonts::font_paths(), collapse = "\n")) - all_fonts <- sysfonts::font_files() - message(paste(all_fonts[all_fonts$family %in% c("Whitney Medium", "Whitney Book", "Whitney Semibold") & all_fonts$face=="Regular", "file"], collapse = "\n")) + all_fonts <- systemfonts::system_fonts() + message("WHITNEY FONTS AUTOMATICALLY AVAILABLE TO SYSTEMFONTS:") + message(paste(all_fonts$name[grepl("^Whitney", all_fonts$name)], collapse = "\n")) + user_dir <- paste0(Sys.getenv("HOME"), "/Library/Fonts") + library_fonts <- list.files(user_dir) + message(paste0("WHITNEY FONTS IN ", user_dir, " (MUST BE REGISTERED):")) + message(paste(library_fonts[grepl("^Whitney", library_fonts)], collapse = "\n")) shell: Rscript {0} - name: Install package run: R CMD INSTALL . - - name: Deploy package + - name: Deploy package to live branch + if: ${{ github.ref == 'refs/heads/main' }} run: | + echo "This is $GITHUB_REF. Deploying to gh-pages branch." git config --local user.email "actions@github.com" git config --local user.name "GitHub Actions" - Rscript -e 'pkgdown::deploy_to_branch(new_process = FALSE, clean = TRUE)' + Rscript -e 'pkgdown::deploy_to_branch(clean = TRUE)' + + - name: Deploy package to test branch + if: ${{ github.ref != 'refs/heads/main' }} + run: | + echo "This is $GITHUB_REF. Deploying to gh-pages-test branch." + git config --local user.email "actions@github.com" + git config --local user.name "GitHub Actions" + Rscript -e 'pkgdown::deploy_to_branch(branch="gh-pages-test", clean = TRUE)' diff --git a/DESCRIPTION b/DESCRIPTION index d9b92bf0..8facfcb2 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -48,10 +48,12 @@ Imports: lubridate, magrittr, purrr, + ragg, rlang, + rstudioapi, scales, stringr, - sysfonts + systemfonts Suggests: knitr, rmarkdown, diff --git a/NAMESPACE b/NAMESPACE index 4cead533..7c85bff0 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -21,11 +21,13 @@ export(cmap_fill_highlight) export(cmap_fill_race) export(cmap_gradients) export(cmap_palettes) -export(cmapplot_globals) export(finalize_plot) export(geom_recessions) export(geom_text_lastonly) +export(get_cmapplot_global) +export(get_cmapplot_globals) export(gg_lwd_convert) +export(set_cmapplot_global) export(theme_cmap) export(unapply_cmap_default_aes) export(update_recessions) @@ -38,7 +40,9 @@ import(graphics) import(grid) import(gridtext) import(rlang) +import(rstudioapi) import(scales) +import(systemfonts) importFrom(generics,intersect) importFrom(ggpubr,get_legend) importFrom(glue,glue) @@ -55,6 +59,5 @@ importFrom(stats,na.omit) importFrom(stringr,str_length) importFrom(stringr,str_replace) importFrom(stringr,str_trunc) -importFrom(sysfonts,font_files) importFrom(utils,modifyList) importFrom(utils,read.csv) diff --git a/R/cmapplot.R b/R/cmapplot.R index ed9086f9..febdc0ea 100644 --- a/R/cmapplot.R +++ b/R/cmapplot.R @@ -11,300 +11,133 @@ #' #' @name cmapplot #' @docType package -#' @import ggplot2 dplyr grid scales grDevices graphics rlang gridtext +#' @import dplyr ggplot2 graphics grDevices grid gridtext rlang scales systemfonts #' @importFrom glue glue glue_collapse -#' @importFrom sysfonts font_files #' @keywords internal "_PACKAGE" -#'cmapplot global variables -#' -#'A list of predefined variables for use by the cmapplot package and its users. -#'It includes commonly used colors, font and font size specifications, and a -#'list of constants which aid in drawing cmap-themed plots. -#' -#'@section Plot Constants: The only portion of these global variables of -#' interest to the user is \code{cmapplot_globals$consts}, a list of default -#' constants that set certain plot aesthetics. Units of all plot constants are -#' "bigpts": 1/72 of an inch. Most plot constants are invoked (and can be -#' overridden) in \code{\link{finalize_plot}}: these are marked below with an -#' \strong{F}. Some are used/can be overridden in \code{\link{theme_cmap}}: -#' these are marked with \strong{T}. -#' -#' \itemize{ \item \code{lwd_strongline}: This stronger-width line is drawn -#' vertically or horizontally with the \code{hline, vline} args of -#' \code{theme_cmap()}. \strong{(T)} \item \code{lwd_gridline}: This -#' thinner-width line is drawn vertically or horizontally with the -#' \code{gridlines, axislines} args of \code{theme_cmap()}. \strong{(T)} \item -#' \code{lwd_plotline}: The width of any lines drawn by geoms in the plot (e.g. -#' \code{geom_line}) but not explicitly sized by the geom's aesthetic. -#' Implemented by \code{finalize_plot} or by \code{apply_cmap_default_aes} but -#' not overridable in either context. (Modify by setting the size explicitly in -#' the geom, but see \code{gg_lwd_convert} first.) \item \code{lwd_topline}: -#' The width of the line above the plot. \strong{(F)} \item -#' \code{length_ticks}: The length of the axis ticks (if shown). \strong{(T)} -#' \item \code{margin_topline_t}: The margin between the top edge of the image -#' and the top line. \strong{(F)} \item \code{margin_title_t}: The margin -#' between the top line and the title. \strong{(F)} \item -#' \code{margin_title_b}: The margin between the title and the caption when -#' both are drawn in the sidebar. \strong{(F)} \item \code{margin_caption_b}: -#' The margin between the bottom of the caption and the bottom edge of the -#' image. \strong{(F)} \item \code{margin_legend_t}: The margin between the top -#' line and the plot box (i.e., the top of the legend). \strong{(F)} \item -#' \code{margin_legend_i}: The margin between legends (this only applies in -#' plots with two or more legends and does not affect legend spacing on plots -#' with single legends that have multiple rows). \strong{(T, F)} \item -#' \code{margin_legend_b}: The margin between the bottom of the legend and the -#' rest of the plot. \strong{(T, F)} \item \code{margin_plot_b}: The margin -#' between the bottom of the plot and the bottom edge of the image (or top of -#' caption). \strong{(F)} \item \code{margin_sidebar_l}: The margin between the -#' left edge of the image and the title and caption, when the sidebar exists. -#' Deducted from \code{title_width}. \strong{(F)} \item \code{margin_plot_l}: -#' The margin between the left edge of the plot and the sidebar. \strong{(F)} -#' \item \code{margin_plot_r}: The margin between the right edge of the plot -#' and the edge of the image. \strong{(F)} \item \code{margin_panel_r}: Padding -#' between the plot and its right-hand drawing extent. Override this based on -#' space needed for x axis labels. \strong{(T)} \item \code{leading_title}: -#' Text leading for Title text. \strong{(F)} \item \code{leading_caption}: Text -#' leading for Caption text. \strong{(F)} } -#' -#'@export -cmapplot_globals <- list( - - ## Colors - colors = list( - blackish = "#222222" - ), - - ## Font sizes - fsize = list( - S = 11, - M = 14, - L = 17 - ), - - ## Base typefaces -- modified later by .onLoad() - font = list( - strong = list(family = "Arial", face = "bold"), - regular = list(family = "Arial", face = "plain"), - light = list(family = "Arial", face = "plain") - ), - use_whitney = FALSE, - - ## Establish plotting constants in bigpts (1/72 of inch) - consts = list( - lwd_gridline = 0.3, - lwd_strongline = 1, - lwd_plotline = 3, - lwd_topline = 2, - length_ticks = 7, - margin_topline_t = 5, - margin_title_t = 5, - margin_title_b = 5, - margin_caption_b = 5, - margin_legend_t = 5, - margin_legend_i = 8, - margin_legend_b = 10, - margin_plot_b = 5, - margin_sidebar_l = 2, - margin_plot_l = 10, - margin_plot_r = 10, - margin_panel_r = 10, - leading_title = 1, - leading_caption = 1 - ), - - # list of geoms whose aesthetics will be customized - geoms_that_change = c( - "Label", - "Line", - "Text", - "TextLast", - "PointLast", - "RecessionsText" - ), - - # empty location for loading in preferred aesthetics during `.onLoad` - default_aes_cmap = NULL, - - # empty location for caching existing aesthetics during `.onLoad` - default_aes_cached = NULL - -) - -## Update fonts based on system -- *must* be done with .onLoad() +#' Update fonts based on system -- *must* be done with .onLoad() +#' +#' @noRd +#' @import rstudioapi .onLoad <- function(...) { - # Check for Whitney - all_fonts <- sysfonts::font_files() - whitney_fonts <- all_fonts[all_fonts$family %in% c("Whitney Medium", "Whitney Book", "Whitney Semibold") & all_fonts$face=="Regular", ] - cmapplot_globals$use_whitney <<- length(whitney_fonts$family) >= 3 + family <- name <- path <- NULL - # Font handling for Windows users - if (.Platform$OS.type == "windows") { + # If font registry already contains Whitney core, set use_whitney == TRUE + fonts_present <- systemfonts::registry_fonts() %>% + dplyr::filter(family %in% cmapplot_globals$preferred_font) %>% + nrow() >= 12 - # Use Whitney if available - if (cmapplot_globals$use_whitney) { - # Add fonts to R - grDevices::windowsFonts( - `Whitney Medium` = grDevices::windowsFont("Whitney Medium"), - `Whitney Book` = grDevices::windowsFont("Whitney Book"), - `Whitney Semibold` = grDevices::windowsFont("Whitney Semibold") - ) + assign("use_whitney", + fonts_present, + envir = cmapplot_globals) - # Update font variables - cmapplot_globals$font <<- list( - strong = list(family = "Whitney Semibold", face = "plain"), - regular = list(family = "Whitney Medium", face = "plain"), - light = list(family = "Whitney Book", face = "plain") - ) - # Otherwise, use Calibri - } else { - packageStartupMessage( - "WARNING: Whitney is not installed on this PC, so CMAP theme will default to Calibri" - ) - # Add fonts to R - grDevices::windowsFonts( - `Calibri` = grDevices::windowsFont("Calibri"), - `Calibri Light` = grDevices::windowsFont("Calibri Light") - ) + # Else, Find and register necessary Whitney variants using systemfonts (or, + # alternatively, find them manually in ~/Library/Fonts). Then, if font + # registry contains Whitney core, set use_whitney == TRUE. + if(!get("use_whitney", envir = cmapplot_globals)){ + whitney_paths <- dplyr::filter(systemfonts::system_fonts(), family == "Whitney") + whitney_paths <- whitney_paths[["path"]] - # Update font variables - cmapplot_globals$font <<- list( - strong = list(family = "Calibri", face = "bold"), - regular = list(family = "Calibri", face = "plain"), - light = list(family = "Calibri Light", face = "plain") - ) + # On some OSX systems (e.g. pkgdown GHA VM) system_fonts() cannot find fonts + # installed in the user fonts directory. In any case where system_fonts() + # sees no Whitney fonts, if `user_dir` exists, it too is checked for fonts. + user_dir <- paste0(Sys.getenv("HOME"), "/Library/Fonts") + if(length(whitney_paths) == 0 & dir.exists(user_dir)){ + whitney_paths <- list.files(user_dir, full.names = TRUE) + whitney_paths <- grep("Whitney-", whitney_paths, value = TRUE) } - # Font handling for macOS/Linux/Unix - } else { - - # Use Whitney if available - if (cmapplot_globals$use_whitney) { - # Add fonts to R - grDevices::X11Fonts( - `Whitney Medium` = grDevices::X11Font("-*-whitney-medium-%s-*-*-%d-*-*-*-*-*-*-*"), - `Whitney Book` = grDevices::X11Font("-*-whitney-book-%s-*-*-%d-*-*-*-*-*-*-*"), - `Whitney Semibold` = grDevices::X11Font("-*-whitney-semibold-%s-*-*-%d-*-*-*-*-*-*-*") - ) - - # Update font variables - cmapplot_globals$font <<- list( - strong = list(family = "Whitney Semibold", face = "plain"), - regular = list(family = "Whitney Medium", face = "plain"), - light = list(family = "Whitney Book", face = "plain") - ) + # Register preferred fonts using the paths found above. This will only be + # attempted if at least 10 paths are found, as 10 distinct faces are needed + # to register all possible variants of the three needed fonts. If the + # correct face cannot be found, `find_path` will error and the try object + # will fail before `use_whitney` is set to TRUE. + if (length(whitney_paths) >= 10){ + try({ + + # register preferred strong font (Whitney Semibold), with variants + systemfonts::register_font( + name = cmapplot_globals$preferred_font$strong, + plain = find_path("Whitney-Semibold-Adv", whitney_paths), + bold = find_path("Whitney-Black-Adv", whitney_paths), + italic = find_path("Whitney-SemiboldItal-Adv", whitney_paths), + bolditalic = find_path("Whitney-BlackItal-Adv", whitney_paths) + ) + + # register preferred regular font (Whitney Medium), with variants + systemfonts::register_font( + name = cmapplot_globals$preferred_font$regular, + plain = find_path("Whitney-Medium-Adv", whitney_paths), + bold = find_path("Whitney-Bold-Adv", whitney_paths), + italic = find_path("Whitney-MediumItal-Adv", whitney_paths), + bolditalic = find_path("Whitney-BoldItal-Adv", whitney_paths) + ) + + # register preferred light font (Whitney Book), with variants + systemfonts::register_font( + name = cmapplot_globals$preferred_font$light, + plain = find_path("Whitney-Book-Adv", whitney_paths), + bold = find_path("Whitney-Semibold-Adv", whitney_paths), + italic = find_path("Whitney-BookItal-Adv", whitney_paths), + bolditalic = find_path("Whitney-SemiboldItal-Adv", whitney_paths) + ) + + packageStartupMessage(paste0( + "cmapplot has registered the following fonts for use in this R session:\n ", + paste(cmapplot_globals$preferred_font, collapse = ", ") + )) + + assign("use_whitney", + TRUE, + envir = cmapplot_globals) + }) + } + } - # Otherwise, stick to Arial (set prior to .onLoad()) - } else { - packageStartupMessage( - "WARNING: Whitney is not installed on this system, so CMAP theme will default to Arial" - ) + # If Whitney is available... + if(get("use_whitney", envir = cmapplot_globals)){ + # ... Update font names + assign("font", + list(strong = list(family = cmapplot_globals$preferred_font$strong, face = "plain"), + regular = list(family = cmapplot_globals$preferred_font$regular, face = "plain"), + light = list(family = cmapplot_globals$preferred_font$light, face = "plain")), + envir = cmapplot_globals) + + # ... and check on rstudio graphics + if (rstudioapi::isAvailable()){ + if(rstudioapi::getVersion() > 1.4){ + if(getOption("RStudioGD.backend") != "ragg"){ + options(RStudioGD.backend = "ragg") + packageStartupMessage(paste( + "cmapplot has set RStudio graphics to `ragg` for the current session.", + "You can make this change permanent:\n ", + "Tools > Global Options > General > Graphics > Graphics Device > Backend == 'AGG'." + )) + } + } else { + packageStartupMessage(paste( + "cmapplot requires RStudio v1.4 or greater to use Whitney fonts", + "in the R plots window. Please upgrade RStudio.")) + } } + # Otherwise, notify user + } else { + packageStartupMessage( + "cmapplot cannot locate Whitney fonts, so CMAP themes will use your default sans-serif font." + ) } # Load CMAP preferred default.aes (can't be done until fonts are specified) - cmapplot_globals$default_aes_cmap <<- init_cmap_default_aes() + assign("default_aes_cmap", + init_cmap_default_aes(), + envir = cmapplot_globals) # Cache existing default.aes - cmapplot_globals$default_aes_cached <<- fetch_current_default_aes() -} - - -# Font spec visualization helper function --------------------------------- - -display_cmap_fonts <- function() { - graphics::plot(c(0,2), c(0,6), type="n", xlab="", ylab="") - - draw.me <- function(name, font, size, placement){ - thisfont <- cmapplot_globals$font[[font]] - thissize <- cmapplot_globals$fsize[[size]] - - graphics::par(family=thisfont$family, - font=ifelse(thisfont$face == "bold", 2, 1)) - graphics::text(1, placement, - paste(name, - paste(paste("font:", font), paste("size:", size), sep = ", "), - paste(thisfont$family, thisfont$face, thissize, sep = ", "), - sep = " | "), - cex=thissize/12, ps=12) - } - - draw.me(name = "Title", font = "strong", size = "L", 5) - draw.me(name = "Main", font = "regular", size = "M", 4) - draw.me(name = "Axis", font = "light", size = "M", 3) - draw.me(name = "Label", font = "strong", size = "M", 2) - draw.me(name = "Note", font = "light", size = "S", 1) -} - - -# Plot sizes and colors --------------------------------------------------- - - -#' Line width conversion -#' -#' The factor \code{.lwd} is used to calculate correct output sizes for line -#' widths. For line widths in \code{ggplot2}, the size in mm must be divided -#' by this factor for correct output. Because the user is likely to prefer -#' other units besides for mm, \code{gg_lwd_convert()} is provided as a -#' convenience function, converting from any unit all the way to ggplot units. -#' -#' \code{.lwd} is equal to \code{ggplot2::.stroke / ggplot2::.pt}. In -#' \code{ggplot2}, the size in mm is divided by \code{.lwd} to achieve the -#' correct output. In the \code{grid} package, however, the size in points -#' (\code{pts} (or maybe \code{bigpts}? Unclear.) must be divided by -#' \code{.lwd}. The user is unlikely to interact directly with \code{grid}, -#' but this is how \code{finalize_plot()} does its work. -#' -#' This is closely related to \code{ggplot::.pt}, which is the factor that -#' font sizes (in \code{pts}) must be divided by for text geoms within -#' \code{ggplot2}. Confusingly, \code{.pt} is not required for \code{ggplot2} -#' font sizes outside the plot area: e.g. axis titles, etc. -#' -#' @seealso grid's \code{\link[grid]{unit}}, ggplot2's -#' \code{\link[ggplot2]{.pt}}, and -#' \url{https://stackoverflow.com/questions/17311917/ggplot2-the-unit-of-size} -#' -#' @examples -#' ggplot() + coord_cartesian(xlim = c(-3, 3), ylim = c(-3, 3)) + -#' -#' # a green line 3 points wide -#' geom_hline(yintercept = 1, color = "green", size = gg_lwd_convert(3)) + -#' -#' # black text of size 24 points -#' annotate("text", -2, 0, label = "text", size = 24/ggplot2::.pt) -#' -#' -#' # a blue line 6 points wide, drawn over the plot with the `grid` package -#' grid::grid.lines(y = 0.4, -#' gp = grid::gpar(col = "blue", lwd = 6 / .lwd)) -#' -#' -#' @export -.lwd <- ggplot2::.pt / ggplot2::.stroke - - -#' Helper function to calculate correct size for ggplot line widths. -#' -#' @param value Numeric, the value to be converted. -#' @param unit Char, the unit of the value to be converted. Can be any of the -#' units accepted by \code{grid::unit()}, including "bigpts", "pt", "mm", and -#' "in". Default is \code{bigpts}. -#' -#' @describeIn dot-lwd Function to convert from any unit directly to ggplot2's -#' preferred millimeters. -#' -#' @export -gg_lwd_convert <- function(value, unit = "bigpts") { - - # convert input type to mm - value_out <- grid::convertUnit(grid::unit(value, unit), "mm", valueOnly = TRUE) - - # return with conversion factor - return( - value_out / .lwd - ) + assign("default_aes_cached", + fetch_current_default_aes(), + envir = cmapplot_globals) } diff --git a/R/cmapplot_globals.R b/R/cmapplot_globals.R new file mode 100644 index 00000000..a86f2c3e --- /dev/null +++ b/R/cmapplot_globals.R @@ -0,0 +1,215 @@ +# Initialize environment for cmapplot global variables +cmapplot_globals <- new.env(parent = emptyenv()) + +# Establish names of preferred fonts +cmapplot_globals$preferred_font <- list( + strong = "Whitney Semibold", + regular = "Whitney Medium", + light = "Whitney Book" +) + +# Set up default font handling +# (Note: overridden by .onLoad() if Whitney is available) +cmapplot_globals$use_whitney <- FALSE +cmapplot_globals$font <- list( + strong = list(family = "sans", face = "bold"), + regular = list(family = "sans", face = "plain"), + light = list(family = "sans", face = "plain")) + +# Set common font sizes (pts) +cmapplot_globals$fsize <- list( + S = 11, + M = 14, + L = 17 +) + +# Define CMAP colors +cmapplot_globals$colors <- list( + blackish = "#222222" +) + +# Establish plotting constants in bigpts (1/72 of inch) +cmapplot_globals$consts <- list( + lwd_gridline = 0.3, + lwd_strongline = 1, + lwd_plotline = 3, + lwd_topline = 2, + length_ticks = 7, + margin_topline_t = 5, + margin_title_t = 5, + margin_title_b = 5, + margin_caption_b = 5, + margin_legend_t = 5, + margin_legend_i = 8, + margin_legend_b = 10, + margin_plot_b = 5, + margin_sidebar_l = 2, + margin_plot_l = 10, + margin_plot_r = 10, + margin_panel_r = 10, + leading_title = 1, + leading_caption = 1 +) + +# List of all geoms whose aesthetics will be modified by cmapplot +cmapplot_globals$geoms_that_change <- c( + "Label", + "Line", + "Text", + "TextLast", + "PointLast", + "RecessionsText" +) + + +#'The cmapplot_globals environment +#' +#'The \code{cmapplot_globals} environment contains a list of predefined +#'variables for use by the cmapplot package and its users. It includes commonly +#'used colors, font and font size specifications, and a list of constants which +#'aid in drawing cmap-themed plots. It cannot be accessed directly, but the +#'helper functions described here provide the user access if needed. +#' +#'@section Plot Constants: The primary portion of these global variables of +#' interest to the user is \code{cmapplot_globals$consts}, a list of default +#' constants that set certain plot aesthetics. Units of all plot constants are +#' "bigpts": 1/72 of an inch. Most plot constants are invoked (and can be +#' overridden) in \code{\link{finalize_plot}}: these are marked below with an +#' \strong{F}. Some are used/can be overridden in \code{\link{theme_cmap}}: +#' these are marked with \strong{T}. +#' +#' \itemize{ \item \code{lwd_strongline}: This stronger-width line is drawn +#' vertically or horizontally with the \code{hline, vline} args of +#' \code{theme_cmap()}. \strong{(T)} \item \code{lwd_gridline}: This +#' thinner-width line is drawn vertically or horizontally with the +#' \code{gridlines, axislines} args of \code{theme_cmap()}. \strong{(T)} \item +#' \code{lwd_plotline}: The width of any lines drawn by geoms in the plot (e.g. +#' \code{geom_line}) but not explicitly sized by the geom's aesthetic. +#' Implemented by \code{finalize_plot} or by \code{apply_cmap_default_aes} but +#' not overridable in either context. (Modify by setting the size explicitly in +#' the geom, but see \code{gg_lwd_convert} first.) \item \code{lwd_topline}: +#' The width of the line above the plot. \strong{(F)} \item +#' \code{length_ticks}: The length of the axis ticks (if shown). \strong{(T)} +#' \item \code{margin_topline_t}: The margin between the top edge of the image +#' and the top line. \strong{(F)} \item \code{margin_title_t}: The margin +#' between the top line and the title. \strong{(F)} \item +#' \code{margin_title_b}: The margin between the title and the caption when +#' both are drawn in the sidebar. \strong{(F)} \item \code{margin_caption_b}: +#' The margin between the bottom of the caption and the bottom edge of the +#' image. \strong{(F)} \item \code{margin_legend_t}: The margin between the top +#' line and the plot box (i.e., the top of the legend). \strong{(F)} \item +#' \code{margin_legend_i}: The margin between legends (this only applies in +#' plots with two or more legends and does not affect legend spacing on plots +#' with single legends that have multiple rows). \strong{(T, F)} \item +#' \code{margin_legend_b}: The margin between the bottom of the legend and the +#' rest of the plot. \strong{(T, F)} \item \code{margin_plot_b}: The margin +#' between the bottom of the plot and the bottom edge of the image (or top of +#' caption). \strong{(F)} \item \code{margin_sidebar_l}: The margin between the +#' left edge of the image and the title and caption, when the sidebar exists. +#' Deducted from \code{title_width}. \strong{(F)} \item \code{margin_plot_l}: +#' The margin between the left edge of the plot and the sodebar. \strong{(F)} +#' \item \code{margin_plot_r}: The margin between the right edge of the plot +#' and the edge of the image. \strong{(F)} \item \code{margin_panel_r}: Padding +#' between the plot and its right-hand drawing extent. Override this based on +#' space needed for x axis labels. \strong{(T)} \item \code{leading_title}: +#' Text leading for Title text. \strong{(F)} \item \code{leading_caption}: Text +#' leading for Caption text. \strong{(F)} } +#' +#' @aliases cmapplot_globals +#' +#' @describeIn get_cmapplot_globals Get the entire environment as a list. +#' +#' @export +get_cmapplot_globals <- function(){ + as.list(cmapplot_globals) +} + +#' Get a value from the cmapplot_globals environment +#' +#' @examples +#' +#' # These are the same: +#' get_cmapplot_global("consts$lwd_gridline") +#' get_cmapplot_global("consts", "lwd_gridline") +#' +#' @describeIn get_cmapplot_globals Get a specific global value +#' +#' @export +get_cmapplot_global <- function(...){ + + # establish vector of sublocations + names <- unlist(stringr::str_split(c(...), "\\$")) + + # fetch the top-level element from the list + var <- get(names[1], envir = cmapplot_globals) + + # recurse over additional names to extract the right value + for(i in seq_along(names[-1])+1){ + var <- var[[names[i]]] + } + + if(is.null(var)){ + stop(paste0("object '", paste(names, collapse = "$"), "' not found")) + } + + return(var) + +} + + +#' Set a value in the cmapplot_globals environment +#' +#' @param value the value to be set +#' +#' @param ... The path to the variable within \code{cmapplot_globals} to be +#' get/set. The function willparse \code{$}, or recursive list elements can be +#' split over multiple arguments (e.g. \code{"font$strong$family"} is +#' equivalent to \code{"font", "strong", "family"}). +#' +#' @param quietly suppress confirmatory messages +#' +#' @examples +#' +#' # Globals can be modified if needed +#' set_cmapplot_global(5, "consts$lwd_gridline") +#' get_cmapplot_global("consts$lwd_gridline") +#' +#' @describeIn get_cmapplot_globals Set a specific global value +#' +#' @export +set_cmapplot_global <- function(value, ..., quietly = FALSE){ + + # do a get of the specific attribute to make sure it exists. + # this will error if the path is null + p <- get_cmapplot_global(...) + + # establish vector of sublocations + names <- unlist(stringr::str_split(c(...), "\\$")) + + # get the top-level item + item <- get_cmapplot_global(names[1]) + + # build a string to evaluate that modifies some element of the item. + str <- paste0( + "item", + ifelse(length(names) > 1, paste0("$", paste(names[-1], collapse = "$")), ""), + " <- ", + ifelse(is.character(value), paste0("'", value, "'"), value) + ) + + # replace the specific item by evaluating the string + eval(parse(text = str)) + + # and replace the top level item in the globals env + assign(names[1], item, envir = cmapplot_globals) + + # report + if(!quietly){ + cat(paste0( + "Item: ", paste(names, collapse = "$"), "\n", + "Old value: ", ifelse(is.character(p), paste0("'", p, "'"), p), "\n", + "New value: ", ifelse(is.character(value), paste0("'", value, "'"), value) + )) + } + invisible() +} diff --git a/R/default_aes.R b/R/default_aes.R index 4cf716d8..7cdc7a26 100644 --- a/R/default_aes.R +++ b/R/default_aes.R @@ -58,7 +58,7 @@ init_cmap_default_aes <- function () { #' style standards, because (at least at the moment) setting geom aesthetic #' defaults on a plot-by-plot basis (such as with \code{ggplot2::theme}) is not #' possible. The geoms impacted are stored in -#' \code{cmapplot_globals$geoms_to_change}. +#' \code{cmapplot_globals$geoms_that_change}. #' #' These functions are employed implicitly within \code{\link{finalize_plot}} to #' apply preferred aesthetic defaults to final outputs. They are only necessary diff --git a/R/finalize_plot.R b/R/finalize_plot.R index b24906bd..debb832d 100644 --- a/R/finalize_plot.R +++ b/R/finalize_plot.R @@ -721,23 +721,3 @@ save_plot <- function(finished_graphic, ) } - - -#' Sub-fn to safely intepret grobHeight -#' -#' This returns the height of Grob in any real unit. -#' If the value passed in is null, it returns 0. -#' -#' @noRd -safe_grobHeight <- function(grob, unitTo = "bigpts", valueOnly = TRUE){ - - if(is.null(grob)){ - if(valueOnly){ - return(0) - } else { - return(unit(0, unitTo)) - } - } - - return(grid::convertHeight(grid::grobHeight(grob), unitTo, valueOnly)) -} diff --git a/R/theme_cmap.R b/R/theme_cmap.R index 99f2fac3..a2e1c716 100644 --- a/R/theme_cmap.R +++ b/R/theme_cmap.R @@ -7,8 +7,8 @@ #'undesireable outcomes in a ggplot that also invokes \code{coord_flip()}. Under #'the hood, \code{theme_cmap(xlab = "foo")} both sets \code{ggplot2::xlab = #'"foo"} and 'turns on' the ggplot theme element \code{axis.title.x}. With -#'\code{coord_flip()}, the xlab travels with the data (becoming the ylab) but the -#'theme modifier stays on the x axis. To solve this, rewrite your ggplot +#'\code{coord_flip()}, the xlab travels with the data (becoming the ylab) but +#'the theme modifier stays on the x axis. To solve this, rewrite your ggplot #'construction to avoid \code{coord_flip()} or manually turn off and on the #'correct elements from ggplot2's \code{\link[ggplot2]{theme}} function in the #'\code{...} of this function. @@ -20,10 +20,11 @@ #' \code{coord_flip()}. #'@param hline,vline Numeric, the location of a strong horizontal or vertical #' line to be added to the plot. Use \code{hline = 0}, for example, to place a -#' line at y = 0 to differentiate between positive and negative values. The width -#' of this line is determined by \code{cmapplot_globals$lwd_strongline}. Note that -#' on most displays the difference between this line and gridlines is impossible -#' to discern in R. The difference will be visible upon export. +#' line at y = 0 to differentiate between positive and negative values. The +#' width of this line is determined by +#' \code{cmapplot_globals$consts$lwd_strongline}. Note that on most displays +#' the difference between this line and gridlines is impossible to discern in +#' R. The difference will be visible upon export. #'@param gridlines Char, the grid lines to be displayed on the chart. If left as #' default, horizontal grid lines will be displayed while vertical grid lines #' will be masked. Acceptable values are "h" (horizontal only), "v" (vertical @@ -50,8 +51,8 @@ #'@param debug Bool, Defaults to \code{FALSE}. Set to \code{TRUE} to show #' rectangles around all \code{geom_rect()} elements for debugging. #'@param overrides Named list, overrides the default drawing attributes defined -#' in \code{cmapplot_globals$consts} which are drawn by \code{\link{theme_cmap}}. -#' Units are in bigpts (1/72 of an inch). +#' in \code{cmapplot_globals$consts} which are drawn by +#' \code{\link{theme_cmap}}. Units are in bigpts (1/72 of an inch). #'@param ... pass additional arguments to ggplot2's \code{\link[ggplot2]{theme}} #' function to override any elements of the default CMAP theme. #' diff --git a/R/utilities.R b/R/utilities.R new file mode 100644 index 00000000..8c9421c6 --- /dev/null +++ b/R/utilities.R @@ -0,0 +1,143 @@ +# Font spec visualization helper function --------------------------------- + +#' Font visualization test +#' +#' This internal function uses base R graphics to display the five text variants +#' that should show up on a cmap themed graphic - and what fonts the package is +#' planning to use to display them. +#' +#' @noRd +display_cmap_fonts <- function() { + graphics::plot(c(0,2), c(0,6), type="n", xlab="", ylab="") + + draw.me <- function(name, font, size, placement){ + thisfont <- cmapplot_globals$font[[font]] + thissize <- cmapplot_globals$fsize[[size]] + + graphics::par(family=thisfont$family, + font=ifelse(thisfont$face == "bold", 2, 1)) + graphics::text(1, placement, + paste(name, + paste(paste("font:", font), paste("size:", size), sep = ", "), + paste(thisfont$family, thisfont$face, thissize, sep = ", "), + sep = " | "), + cex=thissize/12, ps=12) + } + + draw.me(name = "Title", font = "strong", size = "L", 5) + draw.me(name = "Main", font = "regular", size = "M", 4) + draw.me(name = "Axis", font = "light", size = "M", 3) + draw.me(name = "Label", font = "strong", size = "M", 2) + draw.me(name = "Note", font = "light", size = "S", 1) +} + + + +# Plot sizes and colors --------------------------------------------------- + +#' Line width conversion +#' +#' The factor \code{.lwd} is used to calculate correct output sizes for line +#' widths. For line widths in \code{ggplot2}, the size in mm must be divided +#' by this factor for correct output. Because the user is likely to prefer +#' other units besides for mm, \code{gg_lwd_convert()} is provided as a +#' convenience function, converting from any unit all the way to ggplot units. +#' +#' \code{.lwd} is equal to \code{ggplot2::.stroke / ggplot2::.pt}. In +#' \code{ggplot2}, the size in mm is divided by \code{.lwd} to achieve the +#' correct output. In the \code{grid} package, however, the size in points +#' (\code{pts} (or maybe \code{bigpts}? Unclear.) must be divided by +#' \code{.lwd}. The user is unlikely to interact directly with \code{grid}, +#' but this is how \code{finalize_plot()} does its work. +#' +#' This is closely related to \code{ggplot::.pt}, which is the factor that +#' font sizes (in \code{pts}) must be divided by for text geoms within +#' \code{ggplot2}. Confusingly, \code{.pt} is not required for \code{ggplot2} +#' font sizes outside the plot area: e.g. axis titles, etc. +#' +#' @seealso grid's \code{\link[grid]{unit}}, ggplot2's +#' \code{\link[ggplot2]{.pt}}, and +#' \url{https://stackoverflow.com/questions/17311917/ggplot2-the-unit-of-size} +#' +#' @examples +#' ggplot() + coord_cartesian(xlim = c(-3, 3), ylim = c(-3, 3)) + +#' +#' # a green line 3 points wide +#' geom_hline(yintercept = 1, color = "green", size = gg_lwd_convert(3)) + +#' +#' # black text of size 24 points +#' annotate("text", -2, 0, label = "text", size = 24/ggplot2::.pt) +#' +#' +#' # a blue line 6 points wide, drawn over the plot with the `grid` package +#' grid::grid.lines(y = 0.4, gp = grid::gpar(col = "blue", lwd = 6 / .lwd)) +#' +#' @export +.lwd <- ggplot2::.pt / ggplot2::.stroke + + +#' Helper function to calculate correct size for ggplot line widths. +#' +#' @param value Numeric, the value to be converted. +#' @param unit Char, the unit of the value to be converted. Can be any of the +#' units accepted by \code{grid::unit()}, including "bigpts", "pt", "mm", and +#' "in". Default is \code{bigpts}. +#' +#' @describeIn dot-lwd Function to convert from any unit directly to ggplot2's +#' preferred millimeters. +#' +#' @export +gg_lwd_convert <- function(value, unit = "bigpts") { + + # convert input type to mm + value_out <- grid::convertUnit(grid::unit(value, unit), "mm", valueOnly = TRUE) + + # return with conversion factor + return( + value_out / .lwd + ) +} + + + +#' Identify correct font path based on filename +#' +#' Taking a list of font paths, search for a specific filename. If a perfect +#' match is found, return that path. +#' +#' @param filename the complete file name, less a .otf or .ttf extension. +#' @param path a vector of filepaths +#' +#' @noRd +find_path <- function(filename, paths){ + result <- grep(paste0("(\\\\|/)", filename, ".[ot]tf$"), paths, value = TRUE) + + if(length(result) >= 1){ + return(result[1]) + } else { + stop( + paste0("Font '", filename, "' not found."), + call. = FALSE) + } +} + + +#' Sub-fn to safely intepret grobHeight +#' +#' This returns the height of Grob in any real unit. +#' If the value passed in is null, it returns 0. +#' It is used in various places in `finalize_plot` +#' +#' @noRd +safe_grobHeight <- function(grob, unitTo = "bigpts", valueOnly = TRUE){ + + if(is.null(grob)){ + if(valueOnly){ + return(0) + } else { + return(unit(0, unitTo)) + } + } + + return(grid::convertHeight(grid::grobHeight(grob), unitTo, valueOnly)) +} diff --git a/man/cmap_default_aes.Rd b/man/cmap_default_aes.Rd index 44b99680..4c43639d 100644 --- a/man/cmap_default_aes.Rd +++ b/man/cmap_default_aes.Rd @@ -19,7 +19,7 @@ certain ggplot2 geoms. This is necessary for geoms to be "themed" to CMAP style standards, because (at least at the moment) setting geom aesthetic defaults on a plot-by-plot basis (such as with \code{ggplot2::theme}) is not possible. The geoms impacted are stored in -\code{cmapplot_globals$geoms_to_change}. +\code{cmapplot_globals$geoms_that_change}. } \details{ These functions are employed implicitly within \code{\link{finalize_plot}} to diff --git a/man/dot-lwd.Rd b/man/dot-lwd.Rd index 00356df8..62765db2 100644 --- a/man/dot-lwd.Rd +++ b/man/dot-lwd.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/cmapplot.R +% Please edit documentation in R/utilities.R \docType{data} \name{.lwd} \alias{.lwd} @@ -57,9 +57,7 @@ ggplot() + coord_cartesian(xlim = c(-3, 3), ylim = c(-3, 3)) + # a blue line 6 points wide, drawn over the plot with the `grid` package -grid::grid.lines(y = 0.4, - gp = grid::gpar(col = "blue", lwd = 6 / .lwd)) - +grid::grid.lines(y = 0.4, gp = grid::gpar(col = "blue", lwd = 6 / .lwd)) } \seealso{ diff --git a/man/cmapplot_globals.Rd b/man/get_cmapplot_globals.Rd similarity index 65% rename from man/cmapplot_globals.Rd rename to man/get_cmapplot_globals.Rd index 6467c019..e39f8f93 100644 --- a/man/cmapplot_globals.Rd +++ b/man/get_cmapplot_globals.Rd @@ -1,22 +1,46 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/cmapplot.R -\docType{data} -\name{cmapplot_globals} +% Please edit documentation in R/cmapplot_globals.R +\name{get_cmapplot_globals} +\alias{get_cmapplot_globals} \alias{cmapplot_globals} -\title{cmapplot global variables} -\format{ -An object of class \code{list} of length 8. -} +\alias{get_cmapplot_global} +\alias{set_cmapplot_global} +\title{The cmapplot_globals environment} \usage{ -cmapplot_globals +get_cmapplot_globals() + +get_cmapplot_global(...) + +set_cmapplot_global(value, ..., quietly = FALSE) +} +\arguments{ +\item{...}{The path to the variable within \code{cmapplot_globals} to be +get/set. The function willparse \code{$}, or recursive list elements can be +split over multiple arguments (e.g. \code{"font$strong$family"} is +equivalent to \code{"font", "strong", "family"}).} + +\item{value}{the value to be set} + +\item{quietly}{suppress confirmatory messages} } \description{ -A list of predefined variables for use by the cmapplot package and its users. -It includes commonly used colors, font and font size specifications, and a -list of constants which aid in drawing cmap-themed plots. +The \code{cmapplot_globals} environment contains a list of predefined +variables for use by the cmapplot package and its users. It includes commonly +used colors, font and font size specifications, and a list of constants which +aid in drawing cmap-themed plots. It cannot be accessed directly, but the +helper functions described here provide the user access if needed. } +\section{Functions}{ +\itemize{ +\item \code{get_cmapplot_globals}: Get the entire environment as a list. + +\item \code{get_cmapplot_global}: Get a specific global value + +\item \code{set_cmapplot_global}: Set a specific global value +}} + \section{Plot Constants}{ - The only portion of these global variables of + The primary portion of these global variables of interest to the user is \code{cmapplot_globals$consts}, a list of default constants that set certain plot aesthetics. Units of all plot constants are "bigpts": 1/72 of an inch. Most plot constants are invoked (and can be @@ -53,7 +77,7 @@ list of constants which aid in drawing cmap-themed plots. caption). \strong{(F)} \item \code{margin_sidebar_l}: The margin between the left edge of the image and the title and caption, when the sidebar exists. Deducted from \code{title_width}. \strong{(F)} \item \code{margin_plot_l}: - The margin between the left edge of the plot and the sidebar. \strong{(F)} + The margin between the left edge of the plot and the sodebar. \strong{(F)} \item \code{margin_plot_r}: The margin between the right edge of the plot and the edge of the image. \strong{(F)} \item \code{margin_panel_r}: Padding between the plot and its right-hand drawing extent. Override this based on @@ -62,4 +86,15 @@ list of constants which aid in drawing cmap-themed plots. leading for Caption text. \strong{(F)} } } -\keyword{datasets} +\examples{ + +# These are the same: +get_cmapplot_global("consts$lwd_gridline") +get_cmapplot_global("consts", "lwd_gridline") + + +# Globals can be modified if needed +set_cmapplot_global(5, "consts$lwd_gridline") +get_cmapplot_global("consts$lwd_gridline") + +} diff --git a/man/theme_cmap.Rd b/man/theme_cmap.Rd index 0d6e1ad4..8985c070 100644 --- a/man/theme_cmap.Rd +++ b/man/theme_cmap.Rd @@ -27,10 +27,11 @@ details for unexpected outcomes when using these arguments along with \item{hline, vline}{Numeric, the location of a strong horizontal or vertical line to be added to the plot. Use \code{hline = 0}, for example, to place a -line at y = 0 to differentiate between positive and negative values. The width -of this line is determined by \code{cmapplot_globals$lwd_strongline}. Note that -on most displays the difference between this line and gridlines is impossible -to discern in R. The difference will be visible upon export.} +line at y = 0 to differentiate between positive and negative values. The +width of this line is determined by +\code{cmapplot_globals$consts$lwd_strongline}. Note that on most displays +the difference between this line and gridlines is impossible to discern in +R. The difference will be visible upon export.} \item{gridlines}{Char, the grid lines to be displayed on the chart. If left as default, horizontal grid lines will be displayed while vertical grid lines @@ -64,8 +65,8 @@ be one row of three and another row of two).} rectangles around all \code{geom_rect()} elements for debugging.} \item{overrides}{Named list, overrides the default drawing attributes defined -in \code{cmapplot_globals$consts} which are drawn by \code{\link{theme_cmap}}. -Units are in bigpts (1/72 of an inch).} +in \code{cmapplot_globals$consts} which are drawn by +\code{\link{theme_cmap}}. Units are in bigpts (1/72 of an inch).} \item{...}{pass additional arguments to ggplot2's \code{\link[ggplot2]{theme}} function to override any elements of the default CMAP theme.} @@ -79,8 +80,8 @@ Using either the \code{xlab} or \code{ylab} argument, but not both, will have undesireable outcomes in a ggplot that also invokes \code{coord_flip()}. Under the hood, \code{theme_cmap(xlab = "foo")} both sets \code{ggplot2::xlab = "foo"} and 'turns on' the ggplot theme element \code{axis.title.x}. With -\code{coord_flip()}, the xlab travels with the data (becoming the ylab) but the -theme modifier stays on the x axis. To solve this, rewrite your ggplot +\code{coord_flip()}, the xlab travels with the data (becoming the ylab) but +the theme modifier stays on the x axis. To solve this, rewrite your ggplot construction to avoid \code{coord_flip()} or manually turn off and on the correct elements from ggplot2's \code{\link[ggplot2]{theme}} function in the \code{...} of this function. diff --git a/pkgdown/_pkgdown.yml b/pkgdown/_pkgdown.yml index 4ca43e07..396cc842 100644 --- a/pkgdown/_pkgdown.yml +++ b/pkgdown/_pkgdown.yml @@ -22,13 +22,13 @@ reference: - title: Additional geoms & auxiliary functions - contents: - starts_with("geom_") - - cmap_default_aes + - ends_with("cmap_default_aes") - abbr_years -- title: Color Palettes and Gradients +- title: Color palettes & gradients - contents: - starts_with("viz_") - starts_with("cmap_fill_") -- title: Sample Datasets +- title: Sample datasets - contents: - cluster_jobchange - economy_basic @@ -41,7 +41,7 @@ reference: - vehicle_ownership - title: Lesser used objects - contents: - - cmapplot_globals + - contains("cmapplot_global") - gg_lwd_convert - update_recessions - customproto diff --git a/vignettes/colors.Rmd b/vignettes/colors.Rmd index f5ed7cad..945b924e 100644 --- a/vignettes/colors.Rmd +++ b/vignettes/colors.Rmd @@ -14,7 +14,8 @@ knitr::opts_chunk$set( fig.width = 7, fig.asp = 400/670, fig.retina = 4, - fig.align = "center" + fig.align = "center", + dev = "ragg_png" ) library(tidyverse) diff --git a/vignettes/cookbook.Rmd b/vignettes/cookbook.Rmd index d3f16052..b3d3b319 100644 --- a/vignettes/cookbook.Rmd +++ b/vignettes/cookbook.Rmd @@ -15,7 +15,8 @@ knitr::opts_chunk$set( fig.asp = 400/670, fig.retina = 4, fig.align = "center", - out.width = "100%" + out.width = "100%", + dev = "ragg_png" ) library(tidyverse) diff --git a/vignettes/finalize.Rmd b/vignettes/finalize.Rmd index 44cb9910..ff3063b5 100644 --- a/vignettes/finalize.Rmd +++ b/vignettes/finalize.Rmd @@ -15,7 +15,8 @@ knitr::opts_chunk$set( fig.asp = 400/670, fig.retina = 4, fig.align = "center", - out.width = "100%" + out.width = "100%", + dev = "ragg_png" ) library(tidyverse) @@ -137,9 +138,12 @@ The title and caption blocks take HTML formatting tags, which you can use to man ```{r finalize5, message=FALSE} # A finalized line graph, with text tweaks finalize_plot(plot = p, - title = "Annual
unlinked passenger trips
(in millions)", - caption = "Source: Chicago Metropolitan Agency for Planning - analysis of Regional Transportation Authority data") + title = "Annual unlinked passenger trips
(in millions)", + caption = 'Source: Chicago + Metropolitan Agency for Planning analysis of + RTA1 data. +

+ 1 Regional Transportation Authority') ``` ## Advanced customization @@ -195,9 +199,8 @@ There is a fairly long list of possible margins that can be customized using the Here, the margins are visualized as they impact a finalized plot that has a sidebar: - + Here, the same margins are visualized as they impact a finalized plot with no sidebar: - - + diff --git a/vignettes/installation.Rmd b/vignettes/installation.Rmd index ed3a5224..43f23f09 100644 --- a/vignettes/installation.Rmd +++ b/vignettes/installation.Rmd @@ -41,6 +41,6 @@ After completing these steps, your computer should be ready to use and export gr ## CMAP fonts -CMAP's design standards require the usage of the Whitney typeface. Whitney is not freely available, but rather requires a license. On CMAP computers, which should already have the Whitney font family installed, cmapplot will use Whitney without any issues. If you receive a warning that Whitney is not installed when you load the package, please verify that the Whitney fonts (specifically, the Book, Medium and Semibold variants) are installed in **C:\\Windows\\Fonts**. If it is not, please submit an IT helpdesk request to get it installed. If Whitney *is* already installed and you are receiving the warning message, please reach out to a member of the cmapplot development team. +CMAP's design standards require the usage of the Whitney typeface. Whitney is not freely available, but rather requires a license. On CMAP computers, which should already have the Whitney font family installed, cmapplot will use Whitney without any issues. If you receive a warning that Whitney is not installed when you load the package, please verify that the Whitney fonts (specifically, the Book, Medium and Semibold variants) are installed. If it is not, please submit an IT helpdesk request to get them installed. If Whitney *is* already installed and you are receiving the warning message, please reach out to a member of the cmapplot development team. -Non-CMAP users will have to license Whitney on their own, or else use cmapplot with its fall-back fonts: Calibri (on Windows) or Arial (on macOS/Linux). +Non-CMAP users will have to license Whitney on their own, or else use cmapplot without. The package will default to your system's default sans-serif font, which is likely Arial. diff --git a/vignettes/plots.Rmd b/vignettes/plots.Rmd index 39224d85..6fce73bd 100644 --- a/vignettes/plots.Rmd +++ b/vignettes/plots.Rmd @@ -14,7 +14,8 @@ knitr::opts_chunk$set( fig.width = 7, fig.asp = 400/670, fig.retina = 4, - fig.align = "center" + fig.align = "center", + dev = "ragg_png" ) library(tidyverse)