wch / extrafont

Tools for using fonts in R graphics
315 stars 48 forks source link

Using extrafont within knitr to pdf #82

Open ghost opened 3 years ago

ghost commented 3 years ago

I have succeeded in using extrafont to allow me to use a monospaced font (Lucida Console) in a GMisc multistate diagram in a vanilla RStudio session (so as to assure that columns align):

library(grid)
library(Gmisc)
library(glue)
library(grDevices)
library(extrafont)
windows(height = 4, width = 6.5)
grid.newpage()
windowsFonts(A=windowsFont("TT Lucida Console"))
TxtGp = getOption("boxGrobTxt", default = gpar(fontfamily = "A", fontsize = 9))

Tp <- boxGrob(glue("State 1:  Tp",
                   "  ",
                   "Entered:    72 (IA: 48, IAK: 24)",
                   "Censored:    8 (IA:  7, IAK:  1)",
                   "Failed:     11 (IA:  4, IAK:  7)",
                   "To II:      53 (IA: 37, IAK: 16)",
                   .sep = "\n"), 
              txt_gp = TxtGp, 
              width = .4, height = .4, y = 0.8, x = 0.2)
II <- boxGrob(glue("State 2:  II",
                   "  ",
                   "Entered:    53 (IA: 37, IAK: 16)",
                   "Censored:   30 (IA: 20, IAK: 10)",
                   "Failed:      0 (IA:  0, IAK:  0)",
                   "To LostII:  23 (IA: 17, IAK:  6)",
                   .sep = "\n"), 
              txt_gp = TxtGp, width = .4, height = .4,
              y = 0.8, x = 0.8)
LostII <- boxGrob(glue("State 3:  LostII",
                   "  ",
                   "Entered:    23 (IA:  17, IAK:  6)",
                   "Censored:   18 (IA:  14, IAK:  4)",
                   "Failed:      5 (IA:   3, IAK:  2)",
                   "To Failed:   5 (IA:   3, IAK:  2)",
                       .sep = "\n"),  
                  txt_gp = TxtGp, width = .4, height = .4,
                  y = 0.2, x = 0.8)
Failed <- boxGrob(glue("State 4:  Failed",
                   "  ",
                   "Entered:     16 (IA:  7, IAK:  9)",
                   "Failed:      16 (IA:  7, IAK:  9)",
                       .sep = "\n"), 
                  txt_gp = TxtGp, width = .4, height = .4,
                  y = 0.2, x = 0.2)
Tp; II; LostII; Failed

connectGrob(Tp, II, type = 'horizontal')
connectGrob(II, LostII, type = 'vertical')
connectGrob(LostII, Failed, type = 'horizontal')
connectGrob(Tp, Failed, type = 'vertical')

But when I try to embed the code into a knitr chunk, it fails with a complaint:

Quitting from lines 22-65 (fonttest.Rmd) Error in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, : invalid font type Calls: ... drawDetails -> drawDetails.text -> grid.Call.graphics In addition: Warning messages: 1: In grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, : font family 'A' not found in PostScript font database 2: In grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, : font family 'A' not found in PostScript font database 3: In grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, : font family 'A' not found in PostScript font database ... etc.

This seems to imply that when the code gets to the chunk with the Gmisc graphics, it finds that it can't locate the font in knitr's pdf compiler (given that in knitr, figures are output to file in the course of compilation, then readded to the output LaTex code at the end of compiling the knitr file). I am guessing that I need to add the font to knitr's pdf compiler, which may not be the same as the default R system pdf compiler. I tried using loadfonts() and loadfonts(device="postscript") to the knitr code. Neither of these helped. (I had already installed the tinytex package and TinyTex.)

So, is there a way to use extrafonts within a knitr chunk? If so, what is the appropriate magic? I do realize that as a work around I can build the graphic in a native RStudio session, save it as a pdf file, and then add the graphic manually to the knitr file. But it would be nice to do all this within knitr.

A second question, if I may. The help file for font_import() shows a parameter "pattern" that seems to imply that one can specify a subset of fonts to import, which would save time importing them into a knitr or native RStudio session. But I get an error when I specify: font_import(pattern = 'Lucida'):

font_import(pattern = 'Lucida') Importing fonts may take a few minutes, depending on the number of fonts and the speed of the system. Continue? [y/n] y Scanning ttf files in C:\WINDOWS\Fonts ... Extracting .afm files from .ttf files... Error in data.frame(fontfile = ttfiles, FontName = "", stringsAsFactors = FALSE) : arguments imply differing number of rows: 0, 1

Am I misunderstanding what this parameter is supposed to do?

Thanks for your package, which is a very useful addition to generation of print ready figures. And thanks in advance for any help you can give me about my two questions. Larry Hunsicker

 

ghost commented 3 years ago

Addendum: My RStudio is set to Sweave using pdfLaTex. Is this what I have to add the fonts to? LGH