fix: use full-bleed background rect instead of opaque logo grob
R-CMD-check / R CMD check (push) Successful in 4m4s

The previous fix applied the plot's background to the logo grob
directly, which made it opaque and covered caption/axis text that
overlaps into the logo area via negative margins.

Instead, wrap the entire arrangeGrob composition in a grobTree with
a background rectGrob behind it. This fills transparent areas (logo
strip, padding gaps) with the plot's background color while keeping
the logo grob itself transparent so overlapping text remains visible.
This commit is contained in:
2026-05-19 22:12:03 -06:00
parent ac8e3eb60e
commit 41fe2b6170
+26 -19
View File
@@ -64,15 +64,10 @@ add_logo <- function(plot, logo, margin_param = NULL, font_scale = 1.1,
position <- match.arg(position)
at_top <- grepl("top", position)
# Inherit the plot's background color so the logo strip matches.
# make_logo_grob() uses theme_void() (transparent), so without this the
# logo area falls back to the device default (white).
# Capture the plot's background color so we can fill the entire composed
# grob with it. The logo grob must stay transparent (theme_void) so that
# caption/axis text overlapping via negative margins remains visible.
bg_fill <- plot$theme$plot.background$fill
if (!is.null(bg_fill) && !is.na(bg_fill)) {
logo <- logo + ggplot2::theme(
plot.background = ggplot2::element_rect(fill = bg_fill, color = NA)
)
}
# Inflate text sizes to compensate for arrangeGrob viewport shrinkage.
# All theme text elements use rel() sizing, so scaling the root 'text'
@@ -91,8 +86,8 @@ add_logo <- function(plot, logo, margin_param = NULL, font_scale = 1.1,
} else {
plot <- plot + theme(plot.margin = unit(c(-14, 7, 7, 7), "pt"))
}
arrangeGrob(logo, plot, heights = c(0.1, 0.93),
padding = unit(0.1, "line"))
composed <- arrangeGrob(logo, plot, heights = c(0.1, 0.93),
padding = unit(0.1, "line"))
} else {
# Bottom placement (original behaviour)
if(has_caption(plot)) {
@@ -105,8 +100,18 @@ add_logo <- function(plot, logo, margin_param = NULL, font_scale = 1.1,
} else {
plot <- plot + theme(plot.margin = unit(c(7, 7, -14, 7), "pt"))
}
arrangeGrob(plot, logo, heights = c(0.93, 0.1),
padding = unit(0.1, "line"))
composed <- arrangeGrob(plot, logo, heights = c(0.93, 0.1),
padding = unit(0.1, "line"))
}
# Wrap with a full-bleed background rect so any transparent areas (the
# logo strip, padding gaps) pick up the plot's background color instead
# of the device default (white).
if (!is.null(bg_fill) && !is.na(bg_fill)) {
bg_rect <- grid::rectGrob(gp = grid::gpar(fill = bg_fill, col = NA))
grid::grobTree(bg_rect, composed)
} else {
composed
}
}
@@ -174,13 +179,8 @@ has_caption <- function(gg) {
#' }
add_logo_ga <- function(plot_list, logo, nrow = 1, widths = NULL,
margin_param = NULL, font_scale = 1.1) {
# Inherit the background color from the first plot so the logo strip matches
# Capture the background color from the first plot
bg_fill <- plot_list[[1]]$theme$plot.background$fill
if (!is.null(bg_fill) && !is.na(bg_fill)) {
logo <- logo + ggplot2::theme(
plot.background = ggplot2::element_rect(fill = bg_fill, color = NA)
)
}
# Inflate text sizes to compensate for viewport shrinkage
if (!is.null(font_scale) && font_scale != 1) {
@@ -215,7 +215,14 @@ add_logo_ga <- function(plot_list, logo, nrow = 1, widths = NULL,
hold <- arrangeGrob(grobs = plot_list, nrow = 1, ncol = length(plot_list), widths = widths)
}
arrangeGrob(hold, logo, heights = c(0.93, .07))
composed <- arrangeGrob(hold, logo, heights = c(0.93, .07))
if (!is.null(bg_fill) && !is.na(bg_fill)) {
bg_rect <- grid::rectGrob(gp = grid::gpar(fill = bg_fill, col = NA))
grid::grobTree(bg_rect, composed)
} else {
composed
}
}