wilkelab / gridtext

Improved text rendering support for grid graphics in R
https://wilkelab.org/gridtext
Other
96 stars 17 forks source link

grob heights do not match those from grid::textGrob, even without markdown #18

Open rrprf opened 3 years ago

rrprf commented 3 years ago

Grobs created by 'richtext_grob' and 'textbox_grob' have the same reported width as those from 'textGrob', but different heights. The difference is in part allowing for descenders ('textGrob' seems not to), but also a difference in interline spacing (larger for 'textGrob' even with the same lineheight).

In the spirit of 'drop-in replacement', could a switch be added to make 'richtext_grob' and 'textbox_grob' return grobs with the same dimensions as 'textGrob's for the same text? (Assuming no markdown or HTML of course.) And have that switch exposed at the ggplot level by 'ggtext::geom_richtext' and 'ggtext::geom_textbox'?

A separate, minor issue, also illustrated below: Even with 'use_markdown' FALSE, newline characters ('\n') are ignored but '
' tags are not.

# Illustrate the vertical size issue.

library(grid)
library(gridtext)

f1 <- function(txt, gp, draw=TRUE, trans_br=TRUE) {
  # Use 'grid::textGrob', 'gridtext::richtext_grob', 'gridtext::textbox_grob' 
  # to create grobs for string 'txt', and calculate their sizes.
  grobs <- list()
  # Standard text grob:
  grobs$text <- textGrob(x=0.5, y=0.85, txt, gp=gp)
  if (trans_br) {  # translate '\n' in 'txt' to HTML '<br>', even when
                   # 'use_markdown' is FALSE
    txt <- gsub("\\n", "<br>", txt)
  }
  # 'use_markdown' FALSE:
  grobs$richtext_plain <- richtext_grob(txt, x=0.5, y=0.7, 
                         margin=unit(c(0,0,0,0), "mm"), 
                         padding=unit(c(0,0,0,0), "mm"), r=unit(0, "mm"), 
                         gp=gp, use_markdown=FALSE)
  grobs$textbox_plain <- textbox_grob(txt, x=0.5, y=0.55, width=NULL, 
                         margin=unit(c(0,0,0,0), "mm"), 
                         padding=unit(c(0,0,0,0), "mm"), r=unit(0, "mm"), 
                         gp=gp, use_markdown=FALSE)
  # 'use_markdown' TRUE:
  grobs$richtext_mkdn <- richtext_grob(txt, x=0.5, y=0.4, 
                         margin=unit(c(0,0,0,0), "mm"), 
                         padding=unit(c(0,0,0,0), "mm"), r=unit(0, "mm"), 
                         gp=gp, use_markdown=TRUE)
  grobs$textbox_mkdn <- textbox_grob(txt, x=0.5, y=0.25, width=NULL, 
                         margin=unit(c(0,0,0,0), "mm"), 
                         padding=unit(c(0,0,0,0), "mm"), r=unit(0, "mm"), 
                         gp=gp, use_markdown=TRUE)
  sizes <- lapply(grobs, function(x) { 
                  w <- convertWidth(unit(1, "grobwidth", data=x), "mm", 
                                    valueOnly=TRUE)
                  h <- convertHeight(unit(1, "grobheight", data=x), "mm", 
                                     valueOnly=TRUE)
                  c(w, h) })
  if (draw) {
    grid.newpage()
    y <- c(0.85, 0.70, 0.55, 0.40, 0.25)
    for (i in seq_along(grobs)) {
      grid.rect(x=0.5, y=y[i], width=unit(sizes[[i]][1], "mm"), 
                height=unit(sizes[[i]][2], "mm"), 
                gp=gpar(col="blue", fill=NA))
      grid.draw(grobs[[i]])
    }
  }
  list(grobs=grobs, sizes=sizes)
}

gp <- gpar(fontfamily="serif", fontsize=12, lineheight=1.0)
# (Similar results with "Helvetica".)

rslt <- f1("The quick brown fox jumps over the lazy dog.", gp=gp)
str(rslt$sizes)
# (Widths all the same.  'textGrob' height is smaller:  it does not include 
# descenders, the others do.)

rslt <- f1("This line has no descenders.", gp=gp)
str(rslt$sizes)
# (Same sizes, although line has no descenders.")

rslt <- f1("The quick brown\nfox jumps over\nthe lazy dog.", gp=gp, 
           trans_br=TRUE)  # translate '\n' to '<br>'
str(rslt$sizes)
# (With multiple lines, 'textGrob' is now *taller* than others, but still 
# does not include descenders in last line--just more space between lines.)

rslt <- f1("The quick brown\nfox jumps over\nthe lazy dog.", gp=gp, 
           trans_br=FALSE)
str(rslt$sizes)
# (Even with 'use_markdown' FALSE, 'richtext_grob' and 'textbox_grob' 
# ignore '\n' in text.)