From 7389432122e6fb34c031e16410c6e15b0362c242 Mon Sep 17 00:00:00 2001 From: Ellis Hughes Date: Fri, 3 Apr 2026 15:00:40 -0700 Subject: [PATCH 1/6] update ggplot2 saving to respect the dimensions of the placeholder by default, but fall back on height = 5, width = 6 if needed. Allow for more devices, and image files now either stretch or scale --- R/ggplot2.R | 68 ++++++++++++++++++--- R/pptx.R | 94 ++++++++++++++++++++++------- tests/testthat/test-pptx_file_png.R | 57 ++++++++++++++++- tests/testthat/test-pptx_ggplot.R | 91 ++++++++++++++++++++++++++++ 4 files changed, 277 insertions(+), 33 deletions(-) create mode 100644 tests/testthat/test-pptx_ggplot.R diff --git a/R/ggplot2.R b/R/ggplot2.R index 724fa16..d465ee0 100644 --- a/R/ggplot2.R +++ b/R/ggplot2.R @@ -7,19 +7,69 @@ polish_content_word.ggplot <- function(x, inline = FALSE, ..., height = 5, width polish_content_word(png, inline = inline, ..., height = height, width = width, units = "in", error_call = error_call) } -#' @param width,height,units Plot size in `units` ("in", "cm", "mm", or "px"). -#' defaults to 5 inches tall and 6 inches wide. +#' @param width,height defaults to match the height and width of the placeholder +#' provided. When that cannot be derived, it assumes the plot should be 5 +#' inches tall and 6 inches wide. Users may set the width and height, but they +#' most both be set. #' @param res Plot resolution. Also accepts a string input: "retina" (320), #' "print" (300), or "screen" (72). Applies only to raster output types. +#' @param device what graphic device to use when saving the plot. Can be one of +#' "png","svg", or "jpeg". +#' +#' @param scale Multiplicative scaling factor. #' @rdname polish_content_pptx #' @export -polish_content_pptx.ggplot <- function(x, ph = "", pptx, ..., height = 5, width = 6, units = "in", res = 300, error_call = current_env()){ - png <- polish_ggplot(x, height = height, width = width, units = units, dpi = res) - polish_content_pptx(png, ph = ph, pptx = pptx, ..., height = height, width = width, units = "in", error_call = error_call) +polish_content_pptx.ggplot <- function(x, ph = "", pptx, ..., height = NULL, width = NULL, res = 300, device = c("png","svg","jpeg"), scale = 1, error_call = current_env()){ + + ## get width and height of placeholder if not set + if(is.null(height) & is.null(width)){ + + # wrap ph in a node + sp_ph <- sp_shell(ph) + + if (length(xml_find_all(sp_ph, ".//a:xfrm")) == 1) { + ## gives dimensions of the placehlder in inches + dims <- dim_extract(sp_ph, ".//a:ext", c("cx", "cy")) + height <- dims$cy + width <- dims$cx + image_fit <- "stretch" + }else{ + height <- 5 + width <- 6 + image_fit <- "scale" + } + }else{ + + invalid_dims <- is.null(height) | is.null(width) + if(!is.null(width) & !invalid_dims){ + invalid_dims <- !is.numeric(width) | (length(width) > 1) | isTRUE(width <= 0) + } + if(!is.null(height) & !invalid_dims){ + invalid_dims <- !is.numeric(height) | (length(height) > 1) | isTRUE(height <= 0) + } + + if(invalid_dims){ + + width_value <- width_value %||% "NULL" + height_value <- height %||% "NULL" + + cli_abort(c( + "{.arg height} and {.arg width} must both be set if defining the plot size, and be positive numeric values.", + i="You've supplied for {.arg height} a {.cls {class(height)}} vector with value {.val {height_value}}.", + i="You've supplied for {.arg width} a {.cls {class(width)}} vector with value {.val {width_value}}." + ), call = error_call) + } + + image_fit <- "scale" + } + + png <- polish_ggplot(x, device = device, height = height, width = width, units = "in", dpi = res, scale = scale) + polish_content_pptx(png, ph = ph, pptx = pptx, ..., height = height, width = width, units = "in", image_fit = image_fit, error_call = error_call) } -polish_ggplot <- function(x, ...) { - tmp_png <- tempfile(fileext = ".png") - ggsave(x, filename = tmp_png, ...) - as_file(tmp_png) +polish_ggplot <- function(x, device = c("png","svg","jpeg"), ...) { + device <- match.arg(device) + tmp_img <- tempfile(fileext = paste0(".", device)) + ggsave(x, filename = tmp_img, device = device, ...) + as_file(tmp_img) } diff --git a/R/pptx.R b/R/pptx.R index 5d7fc2f..555d8c1 100644 --- a/R/pptx.R +++ b/R/pptx.R @@ -98,7 +98,6 @@ polish_content_pptx.data.frame <- function(x, ph = '', pptx, ..., table_s #' - "none" (default) puts contents on new lines and indents lists accordingly. #' - "unordered" makes the content bulleted list with indents. #' - "ordered" makes a numbered list with intents. -#' #' @rdname polish_content_pptx #' @export polish_content_pptx.list <- function(x, ph = '', pptx, ..., list_type = c("none","unordered","ordered"), error_call = current_env()){ @@ -131,38 +130,48 @@ polish_content_pptx.list <- function(x, ph = '', pptx, ..., list_type = c # file_ ------------------------------------------------------------------- #' @param guess_size see [officer::external_img] +#' @param image_fit Should the image be distorted to match the dimensions of the placeholder, or scaled up/down and keep dimension ratio (scale). Default is "stretch". +#' @param scale +#' #' @rdname polish_content_pptx #' @export -polish_content_pptx.file_png <- function(x, ph = '', pptx, ..., height = 5, width = 6, guess_size = FALSE, units = "in", error_call = current_env()) { +polish_content_pptx.file_png <- function(x, ph = '', pptx, ..., height = NULL, width = NULL, units = "in", image_fit = c("stretch","scale"), error_call = current_env()) { check_dots_empty(call = error_call) + image_fit <- match.arg(image_fit) + + ## get image size, either pre-defined, or guess size + if(is.null(height) & is.null(width)){ + ext_img <- officer::external_img(x, guess_size = TRUE) + }else{ + ext_img <- officer::external_img(x, width = width, height = height, guess_size = FALSE) + } + + image_definition <- list(dims = attr(ext_img, "dims"), offset = list(top = 0, left = 0)) + # wrap ph in a node sp_ph <- sp_shell(ph) - ext_img <- officer::external_img(x, height = height, width = width, unit = units, guess_size = guess_size) - + ## If placeholder has dims, get them if (length(xml_find_all(sp_ph, ".//a:xfrm")) == 1) { - offsets <- dim_extract(sp_ph, ".//a:off", c("x", "y")) - top <- offsets$y - left <- offsets$x - - dims <- dim_extract(sp_ph, ".//a:ext", c("cx", "cy")) - height <- dims$cy - width <- dims$cx - } else { - height <- attr(ext_img, "dims")$height - width <- attr(ext_img, "dims")$width - top <- 0 - left <- 0 + ph_offsets <- setNames(dim_extract(sp_ph, ".//a:off", c("x", "y")), c("left","top")) + ph_dims <- setNames(dim_extract(sp_ph, ".//a:ext", c("cx", "cy")), c("width","height")) + + if(image_fit == "scale"){ + image_definition <- image_fit_scale(image_definition = image_definition, ph_offsets = ph_offsets, ph_dims = ph_dims) + }else{ + image_definition <- image_fit_stretch(image_definition = image_definition, ph_offsets = ph_offsets, ph_dims = ph_dims) + } + } # make the node xml <- as_xml_pptx(officer::to_pml( x = ext_img, - top = top, - left = left, - height = height, - width = width, + top = image_definition$offset$top, + left = image_definition$offset$left, + height = image_definition$dims$height, + width = image_definition$dims$width, add_ns = TRUE, ln = officer::sp_line(lwd = 0, linecmpd = "sng", lineend = "rnd"), ph = as.character(xml_find_all(sp_ph, "//p:ph")) @@ -201,7 +210,7 @@ polish_content_pptx.file_rtf <- function(x, ph = '', pptx, ..., error_cal check_dots_empty(call = error_call) png_path <- convert_rtf_file_to_png(x) - polish_content_pptx(as_file(png_path), ph = ph, guess_size = TRUE, error_call = error_call) + polish_content_pptx(as_file(png_path), ph = ph, image_fit = "scale", error_call = error_call) } #' @export @@ -210,8 +219,9 @@ polish_content_pptx.file_html <- function(x, ph = '', pptx, ..., error_ca polish_content_pptx( as_file(convert_html_file_to_png(x)), - ph = ph, guess_size = TRUE, error_call = error_call + ph = ph, image_fit = "scale", error_call = error_call ) + } #' @export @@ -220,7 +230,7 @@ polish_content_pptx.file_pdf <- function(x, ph = '', pptx, ..., error_cal polish_content_pptx( as_file(convert_pdf_file_to_png(x)), - ph = ph, guess_size = TRUE, error_call = error_call + ph = ph, image_fit = "scale", error_call = error_call ) } @@ -268,6 +278,44 @@ dim_extract <- function(xml, xpath, attrs = c("x, y")) { out } +image_fit_scale <- function(image_definition, ph_offsets, ph_dims){ + + ## get image ratio + ratio <- image_definition$dims$height/image_definition$dims$width + + ##determine if scaling image for width or for height + ### get potential new width/heights + ratioed_height <- ratio * ph_dims$width + ratioed_width <- ph_dims$height/ratio + + if(ratioed_height <= ph_dims$height){ + img_height <- ratioed_height + img_width <- ph_dims$width + img_top <- ph_offsets$top+((ph_dims$height-img_height)/2) + img_left <- ph_offsets$left + }else{ + img_height <- ph_dims$height + img_width <- ratioed_width + img_top <- ph_offsets$top + img_left <- ph_offsets$left+((ph_dims$width-img_width)/2) + } + + list( + dims = list(height = img_height, width = img_width), + offset = list(top = img_top, left = img_left) + ) + +} + +image_fit_stretch <- function(image_definition, ph_offsets, ph_dims){ + + list( + dims = ph_dims, + offset = ph_offsets + ) + +} + polish_pptx_strings <- function(txt, escape = TRUE, collapse = FALSE, font_color = NULL, font_style = NULL, font_size = NULL, font_typeface = NULL, error_call = caller_env()) { if (escape){ txt <- htmlEscape(txt) diff --git a/tests/testthat/test-pptx_file_png.R b/tests/testthat/test-pptx_file_png.R index d9543be..1166f16 100644 --- a/tests/testthat/test-pptx_file_png.R +++ b/tests/testthat/test-pptx_file_png.R @@ -3,8 +3,13 @@ test_that("polish_content_pptx.file_png() only creates one cNvPr", { ph <- "" + ## create png file p <- ggplot(mtcars, aes(mpg, cyl)) + geom_point() - xml <- polish_content_pptx(p, ph = ph) + temp_png <- tempfile(fileext = ".png") + ggsave(plot = p, filename = temp_png, width = 6, height = 5, units = "in", dpi = 300) + img_file <- as_file(temp_png) + + xml <- polish_content_pptx(img_file, ph = ph) node_cNvPr <- xml2::xml_find_all(xml, ".//p:cNvPr") expect_equal(length(node_cNvPr), 1) @@ -17,3 +22,53 @@ test_that("polish_content_pptx.file_png() only creates one cNvPr", { expect_equal(xml_attr(xml_find_all(xml, ".//a:ext"), "cx"), "7071360") expect_equal(xml_attr(xml_find_all(xml, ".//a:ext"), "cy"), "5829300") }) + + +test_that("polish_content_pptx.file_png() image_fit", { + + suppressWarnings(withr::local_package("ggplot2")) + + ph <- "" + + ## create png file + p <- ggplot(mtcars, aes(mpg, cyl)) + geom_point() + temp_wide_png <- tempfile(fileext = ".png") + ggsave(plot = p, filename = temp_wide_png, width = 6, height = 2, units = "in", dpi = 300) + img_file_wide <- as_file(temp_wide_png) + + temp_tall_png <- tempfile(fileext = ".png") + ggsave(plot = p, filename = temp_tall_png, width = 2, height = 6, units = "in", dpi = 300) + img_file_tall <- as_file(temp_tall_png) + + ## scale image, keeping ratio + xml_scale_wide <- polish_content_pptx(img_file_wide, ph = ph, image_fit = "scale") + xml_scale_tall <- polish_content_pptx(img_file_tall, ph = ph, image_fit = "scale") + + ## wide, keep x offset and width, move y offset and height + expect_equal(xml_attr(xml_find_all(xml_scale_wide, ".//a:off"), "x"), "487680") + expect_equal(xml_attr(xml_find_all(xml_scale_wide, ".//a:off"), "y"), "2216150") + expect_equal(xml_attr(xml_find_all(xml_scale_wide, ".//a:ext"), "cx"), "7071360") + expect_equal(xml_attr(xml_find_all(xml_scale_wide, ".//a:ext"), "cy"), "2357120") + + ## tall, keep y offset and height, move x offset and width + expect_equal(xml_attr(xml_find_all(xml_scale_tall, ".//a:off"), "x"), "3051810") + expect_equal(xml_attr(xml_find_all(xml_scale_tall, ".//a:off"), "y"), "480060") + expect_equal(xml_attr(xml_find_all(xml_scale_tall, ".//a:ext"), "cx"), "1943100") + expect_equal(xml_attr(xml_find_all(xml_scale_tall, ".//a:ext"), "cy"), "5829300") + + ## stretch image to ph + + xml_stretch_wide <- polish_content_pptx(img_file_wide, ph = ph, image_fit = "stretch") + xml_stretch_tall <- polish_content_pptx(img_file_tall, ph = ph, image_fit = "stretch") + + expect_equal(xml_attr(xml_find_all(xml_stretch_wide, ".//a:off"), "x"), "487680") + expect_equal(xml_attr(xml_find_all(xml_stretch_wide, ".//a:off"), "y"), "480060") + expect_equal(xml_attr(xml_find_all(xml_stretch_wide, ".//a:ext"), "cx"), "7071360") + expect_equal(xml_attr(xml_find_all(xml_stretch_wide, ".//a:ext"), "cy"), "5829300") + + expect_equal(xml_attr(xml_find_all(xml_stretch_tall, ".//a:off"), "x"), "487680") + expect_equal(xml_attr(xml_find_all(xml_stretch_tall, ".//a:off"), "y"), "480060") + expect_equal(xml_attr(xml_find_all(xml_stretch_tall, ".//a:ext"), "cx"), "7071360") + expect_equal(xml_attr(xml_find_all(xml_stretch_tall, ".//a:ext"), "cy"), "5829300") + +}) diff --git a/tests/testthat/test-pptx_ggplot.R b/tests/testthat/test-pptx_ggplot.R new file mode 100644 index 0000000..9a7cd80 --- /dev/null +++ b/tests/testthat/test-pptx_ggplot.R @@ -0,0 +1,91 @@ +## defined placeholders +ph_dims_unset <- "" +ph_dims_set <- "" + +test_that("polish_content_word().ggplot - undefined height and width", { + suppressWarnings(withr::local_package("ggplot2")) + + p <- ggplot(mtcars, aes(mpg, cyl)) + geom_point() + + ## provided ph with out set dims/location + xml_dims_unset <- polish_content_pptx(p, ph = ph_dims_unset) + + expect_equal(xml_attr(xml_find_all(xml_dims_unset, ".//a:off"), "x"), "0") + expect_equal(xml_attr(xml_find_all(xml_dims_unset, ".//a:off"), "y"), "0") + expect_equal(xml_attr(xml_find_all(xml_dims_unset, ".//a:ext"), "cx"), "5486400") + expect_equal(xml_attr(xml_find_all(xml_dims_unset, ".//a:ext"), "cy"), "4572000") + + ## provided ph with set dims/location + xml_dims_set <- polish_content_pptx(p, ph = ph_dims_set) + + expect_equal(xml_attr(xml_find_all(xml_dims_set, ".//a:off"), "x"), "487680") + expect_equal(xml_attr(xml_find_all(xml_dims_set, ".//a:off"), "y"), "480060") + expect_equal(xml_attr(xml_find_all(xml_dims_set, ".//a:ext"), "cx"), "7071360") + expect_equal(xml_attr(xml_find_all(xml_dims_set, ".//a:ext"), "cy"), "5829300") + +}) + +test_that("polish_content_word().ggplot - defined height and width,", { + + suppressWarnings(withr::local_package("ggplot2")) + + p <- ggplot(mtcars, aes(mpg, cyl)) + geom_point() + + ## provided ph with out set dims/location + xml_dims_unset <- polish_content_pptx(p, ph = ph_dims_unset, height = 10, width = 12) + + expect_equal(xml_attr(xml_find_all(xml_dims_unset, ".//a:off"), "x"), "0") + expect_equal(xml_attr(xml_find_all(xml_dims_unset, ".//a:off"), "y"), "0") + expect_equal(xml_attr(xml_find_all(xml_dims_unset, ".//a:ext"), "cx"), "10972800") + expect_equal(xml_attr(xml_find_all(xml_dims_unset, ".//a:ext"), "cy"), "9144000") + + ## provided ph with set dims/location, image dims smaller than ph, image ratio of .83333 + xml_dims_set <- polish_content_pptx(p, ph = ph_dims_set, height = 2, width = 2.4) + + expect_equal(xml_attr(xml_find_all(xml_dims_set, ".//a:off"), "x"), "525780") + expect_equal(xml_attr(xml_find_all(xml_dims_set, ".//a:off"), "y"), "480060") + expect_equal(xml_attr(xml_find_all(xml_dims_set, ".//a:ext"), "cx"), "6995160") + expect_equal(xml_attr(xml_find_all(xml_dims_set, ".//a:ext"), "cy"), "5829300") + + ## provided ph with set dims/location, image dims larger than ph, image ratio of .83333 + xml_dims_set <- polish_content_pptx(p, ph = ph_dims_set, height = 10, width = 12) + + expect_equal(xml_attr(xml_find_all(xml_dims_set, ".//a:off"), "x"), "525780") + expect_equal(xml_attr(xml_find_all(xml_dims_set, ".//a:off"), "y"), "480060") + expect_equal(xml_attr(xml_find_all(xml_dims_set, ".//a:ext"), "cx"), "6995160") + expect_equal(xml_attr(xml_find_all(xml_dims_set, ".//a:ext"), "cy"), "5829300") + +}) + +test_that("polish_content_word().ggplot - partially or incorrectly defined height and width,", { + + suppressWarnings(withr::local_package("ggplot2")) + + p <- ggplot(mtcars, aes(mpg, cyl)) + geom_point() + + expect_snapshot( + polish_content_pptx(p, ph = ph_dims_unset, height = NA, width = 12), + error = TRUE + ) + + expect_snapshot( + polish_content_pptx(p, ph = ph_dims_unset, height = NULL, width = 12), + error = TRUE + ) + + expect_snapshot( + polish_content_pptx(p, ph = ph_dims_unset, height = -10, width = 12), + error = TRUE + ) + + expect_snapshot( + polish_content_pptx(p, ph = ph_dims_unset, height = c(10,11), width = 12), + error = TRUE + ) + + expect_snapshot( + polish_content_pptx(p, ph = ph_dims_unset, height = "invalid", width = 12), + error = TRUE + ) + +}) From 9060bb7d8f0ab295b5d0c98dbe649f1fe90bf598 Mon Sep 17 00:00:00 2001 From: Ellis Hughes Date: Fri, 3 Apr 2026 15:02:01 -0700 Subject: [PATCH 2/6] update snapshots for testing --- tests/testthat/_snaps/pptx_ggplot.md | 40 ++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 tests/testthat/_snaps/pptx_ggplot.md diff --git a/tests/testthat/_snaps/pptx_ggplot.md b/tests/testthat/_snaps/pptx_ggplot.md new file mode 100644 index 0000000..5604482 --- /dev/null +++ b/tests/testthat/_snaps/pptx_ggplot.md @@ -0,0 +1,40 @@ +# polish_content_word().ggplot - partially or incorrectly defined height and width, + + Code + polish_content_pptx(p, ph = ph_dims_unset, height = NA, width = 12) + Condition + Error in `polish_content_pptx.ggplot()`: + ! object 'width_value' not found + +--- + + Code + polish_content_pptx(p, ph = ph_dims_unset, height = NULL, width = 12) + Condition + Error in `polish_content_pptx.ggplot()`: + ! object 'width_value' not found + +--- + + Code + polish_content_pptx(p, ph = ph_dims_unset, height = -10, width = 12) + Condition + Error in `polish_content_pptx.ggplot()`: + ! object 'width_value' not found + +--- + + Code + polish_content_pptx(p, ph = ph_dims_unset, height = c(10, 11), width = 12) + Condition + Error in `polish_content_pptx.ggplot()`: + ! object 'width_value' not found + +--- + + Code + polish_content_pptx(p, ph = ph_dims_unset, height = "invalid", width = 12) + Condition + Error in `polish_content_pptx.ggplot()`: + ! object 'width_value' not found + From 779b3e5841d0b5ae81e8ef219b4bb09a68d5baa0 Mon Sep 17 00:00:00 2001 From: Ellis Hughes Date: Fri, 3 Apr 2026 15:04:49 -0700 Subject: [PATCH 3/6] rerun documentation --- man/polish_content_pptx.Rd | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/man/polish_content_pptx.Rd b/man/polish_content_pptx.Rd index d31bfc8..186462f 100644 --- a/man/polish_content_pptx.Rd +++ b/man/polish_content_pptx.Rd @@ -25,10 +25,11 @@ ph = "", pptx, ..., - height = 5, - width = 6, - units = "in", + height = NULL, + width = NULL, res = 300, + device = c("png", "svg", "jpeg"), + scale = 1, error_call = current_env() ) @@ -62,10 +63,10 @@ polish_content_pptx(x, ph = "", pptx, ..., error_call = current_env()) ph = "", pptx, ..., - height = 5, - width = 6, - guess_size = FALSE, + height = NULL, + width = NULL, units = "in", + image_fit = c("stretch", "scale"), error_call = current_env() ) } @@ -92,12 +93,19 @@ running function, e.g. \code{caller_env()}. The function will be mentioned in error messages as the source of the error. See the \code{call} argument of \code{\link[rlang:abort]{abort()}} for more information.} -\item{width, height, units}{Plot size in \code{units} ("in", "cm", "mm", or "px"). -defaults to 5 inches tall and 6 inches wide.} +\item{width, height}{defaults to match the height and width of the placeholder +provided. When that cannot be derived, it assumes the plot should be 5 +inches tall and 6 inches wide. Users may set the width and height, but they +most both be set.} \item{res}{Plot resolution. Also accepts a string input: "retina" (320), "print" (300), or "screen" (72). Applies only to raster output types.} +\item{device}{what graphic device to use when saving the plot. Can be one of +"png","svg", or "jpeg".} + +\item{scale}{} + \item{escape}{Should \code{x} be escaped with \code{\link[htmltools:htmlEscape]{htmltools::htmlEscape()}}} \item{collapse}{If \code{TRUE} a \verb{} element is added between the \verb{} nodes} @@ -118,6 +126,8 @@ defaults to 5 inches tall and 6 inches wide.} \item "ordered" makes a numbered list with intents. }} +\item{image_fit}{Should the image be distorted to match the dimensions of the placeholder, or scaled up/down and keep dimension ratio (scale). Default is "stretch".} + \item{guess_size}{see \link[officer:external_img]{officer::external_img}} } \description{ From bdf92402f0b38b3bb57e78e3b720f0f77685accc Mon Sep 17 00:00:00 2001 From: Ellis Hughes Date: Sun, 5 Apr 2026 17:52:19 -0700 Subject: [PATCH 4/6] update documentation for "Scale" and replace setNames with names()<- --- R/pptx.R | 8 +++++--- man/polish_content_pptx.Rd | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/R/pptx.R b/R/pptx.R index 555d8c1..0d33485 100644 --- a/R/pptx.R +++ b/R/pptx.R @@ -131,7 +131,7 @@ polish_content_pptx.list <- function(x, ph = '', pptx, ..., list_type = c #' @param guess_size see [officer::external_img] #' @param image_fit Should the image be distorted to match the dimensions of the placeholder, or scaled up/down and keep dimension ratio (scale). Default is "stretch". -#' @param scale +#' @param scale Multiplicative scaling factor to use when saving the plot. See [ggplot2::ggsave]. #' #' @rdname polish_content_pptx #' @export @@ -154,8 +154,10 @@ polish_content_pptx.file_png <- function(x, ph = '', pptx, ..., height = ## If placeholder has dims, get them if (length(xml_find_all(sp_ph, ".//a:xfrm")) == 1) { - ph_offsets <- setNames(dim_extract(sp_ph, ".//a:off", c("x", "y")), c("left","top")) - ph_dims <- setNames(dim_extract(sp_ph, ".//a:ext", c("cx", "cy")), c("width","height")) + ph_offsets <- dim_extract(sp_ph, ".//a:off", c("x", "y")) + names(ph_offsets) <- c("left","top") + ph_dims <- dim_extract(sp_ph, ".//a:ext", c("cx", "cy")) + names(ph_dims) <- c("width","height") if(image_fit == "scale"){ image_definition <- image_fit_scale(image_definition = image_definition, ph_offsets = ph_offsets, ph_dims = ph_dims) diff --git a/man/polish_content_pptx.Rd b/man/polish_content_pptx.Rd index 186462f..127b45f 100644 --- a/man/polish_content_pptx.Rd +++ b/man/polish_content_pptx.Rd @@ -104,7 +104,7 @@ most both be set.} \item{device}{what graphic device to use when saving the plot. Can be one of "png","svg", or "jpeg".} -\item{scale}{} +\item{scale}{Multiplicative scaling factor to use when saving the plot. See \link[ggplot2:ggsave]{ggplot2::ggsave}.} \item{escape}{Should \code{x} be escaped with \code{\link[htmltools:htmlEscape]{htmltools::htmlEscape()}}} From 367e83921156fc3a33c7390a6af44d7470ee136f Mon Sep 17 00:00:00 2001 From: Ellis Hughes Date: Sun, 5 Apr 2026 19:37:23 -0700 Subject: [PATCH 5/6] more documentation --- R/pptx.R | 2 +- man/polish_content_pptx.Rd | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/R/pptx.R b/R/pptx.R index 0d33485..436ab85 100644 --- a/R/pptx.R +++ b/R/pptx.R @@ -129,7 +129,7 @@ polish_content_pptx.list <- function(x, ph = '', pptx, ..., list_type = c # file_ ------------------------------------------------------------------- -#' @param guess_size see [officer::external_img] +#' @param units see [officer::external_img] #' @param image_fit Should the image be distorted to match the dimensions of the placeholder, or scaled up/down and keep dimension ratio (scale). Default is "stretch". #' @param scale Multiplicative scaling factor to use when saving the plot. See [ggplot2::ggsave]. #' diff --git a/man/polish_content_pptx.Rd b/man/polish_content_pptx.Rd index 127b45f..2e48187 100644 --- a/man/polish_content_pptx.Rd +++ b/man/polish_content_pptx.Rd @@ -126,9 +126,9 @@ most both be set.} \item "ordered" makes a numbered list with intents. }} -\item{image_fit}{Should the image be distorted to match the dimensions of the placeholder, or scaled up/down and keep dimension ratio (scale). Default is "stretch".} +\item{units}{see \link[officer:external_img]{officer::external_img}} -\item{guess_size}{see \link[officer:external_img]{officer::external_img}} +\item{image_fit}{Should the image be distorted to match the dimensions of the placeholder, or scaled up/down and keep dimension ratio (scale). Default is "stretch".} } \description{ Polish content for Powerpoint From 252bf8dacb7486c42915e66170e29cc92023f324 Mon Sep 17 00:00:00 2001 From: Ellis Hughes Date: Thu, 21 May 2026 10:09:30 -0700 Subject: [PATCH 6/6] update news --- NEWS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS.md b/NEWS.md index 8a745e7..73bd6d6 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,6 @@ # polish 0.3.1 * surface gt as_word argument autonum in polish_content_word.gt_tbl +* Add new feature to polishing figures (including ggplots) to allow choosing to stretch or scaling images to fit placeholders. # polish 3.0.0 * Open source the package