Text in the grid package doesn't really have a size until it is time to draw the text. Below, we'll make a helper function to measure text, but it doesn't really make any sense to do this unless you know the device and size of the plotting area in advance. (For those in the know, during the makeContent()
stage of drawing).
library(grid)
label <- c("label-one-that-might-overlap-another-label",
"label-two-that-might-overlap-another-label")
measure_size <- function(txt, gp = gpar(), to = "mm") {
if (is.grob(txt)) {
grobs <- lapply(seq_along(txt$label), function(i) {
g <- txt
# Subset grob per label
g$label <- g$label[[i]]
g$gp[] <- lapply(g$gp, function(x) {x[pmin(i, length(x))]})
g$rot <- g$rot[pmin(i, length(g$rot))]
g
})
} else {
grobs <- lapply(txt, function(t) textGrob(t, gp = gp))
}
heights <- do.call(unit.c, lapply(grobs, grobHeight))
widths <- do.call(unit.c, lapply(grobs, grobWidth))
cbind(
height = convertHeight(heights, to, valueOnly = TRUE),
weight = convertWidth(widths, to, valueOnly = TRUE)
)
}
We can now try to guess the size of the text as best as we can, but as one might expect, it depends a lot on graphical parameters of text what the actual size is. Notice for example that changing the font also changes the size of the text.
measure_size(label)
#> height weight
#> [1,] 3.175 79.13109
#> [2,] 3.175 78.65566
measure_size(label, gp = gpar(fontfamily = "Garamond"))
#> height weight
#> [1,] 2.645833 69.67223
#> [2,] 2.645833 69.69704
Now applying the same trick to ggplot2's text layer.
library(ggplot2)
#> Warning: package 'ggplot2' was built under R version 4.1.1
df <- data.frame(x = c(1, 2),
y = c(1, 1),
label = label)
p <- ggplot(df, aes(x, y)) +
geom_text(aes(label = label)) +
xlim(0, 3)
textgrob <- layer_grob(p)[[1]]
measure_size(textgrob)
#> height weight
#> [1,] 2.645979 72.83233
#> [2,] 2.645979 72.39411
Created on 2021-12-13 by the reprex package (v2.0.1)
I worked a lot with text recently myself and found that the {systemfonts}/{textshaping} packages accurately return the size of the text in pixels, which is of course device/resolution dependent.
systemfonts::string_width("My label")
#> [1] 46
textshaping::text_width("My label")
#> [1] 46