Using system fonts in R graphs
This is a pretty old topic in R graphics.
A classical article in R NEWS,
Non-standard fonts in PostScript and PDF graphics,
describes how to use and embed system fonts in the PDF/PostScript device.
More recently, Winston Chang developed
the extrafont package, which
makes the procedure much easier. A useful introduction article can be found in the
readme page of
and also from the Revolution blog.
Now, we have another choice: the
We are now much freer to use system fonts in R to create figures.
What’s this package all about?
showtext is an R package to draw text in R graphs.
Wait, R already has
text()function to do that…
Yes, but drawing text is a very complicated task, and it always depends on
the specific Graphics Device.
(Graphics device is the engine to create images.
For example, R provides PDF device, called by function
to create graphs in PDF format)
Sometimes the graphics device doesn’t support text drawing nicely,
especially in using fonts.
From my own experience, I find it always troublesome to create PDF
graphs with Chinese characters. This is because most of the standard
fonts used by
pdf() don’t contain Chinese character glyphs, and
even worse users could hardly use the fonts that are already installed
in their operating system. (It seems still possible, though)
showtext tries to do the following two things:
- Let R know about these system fonts
- Use these fonts to draw text
pdf() doesn’t work and how
Let me explain a little bit about how
To my best knowledge (may be wrong, so please point it out if I make mistakes), the default PDF device of R doesn’t “draw” the text, but actually “describes” the text in the PDF file. That is to say, instead of drawing lines and curves of the actual glyph, it only embeds information about the text, for example what characters it has, which font it uses, etc.
However, the text with declared font may be displayed differently in different OS. The two images below are the screenshots of the same PDF file created by R but viewed under Windows and Linux respectively.
This means that the appearance of graph created by
system dependent. If you unfortunately don’t have the declared font
in your system, you may not be able to see the text correctly at all.
showtext package tries to solve this problem by
converting text into lines and curves, thus having the same appearance
under all platforms. More importantly,
showtext can use system font
files, so you can show your text in any font you want.
This solves the Chinese character problem I mentioned in the beginning
because I can load my favorite Chinese font to R and use that to draw
text. Also, people who view this graph don’t need to install the font
that creates the graph. It provides convenience to both graph makers
and graph viewers.
To create a graph using a specified font, you only need to do:
- (*) Load the font
- Open the graphics device
- (*) Claim that you want to use
showtextto draw the text
- Close the device
Only the steps marked with (*) are newly added. Below is an example:
library(showtext) font.add("fang", "simfang.ttf") ## add font pdf("showtext-ex1.pdf") plot(1, type = "n") showtext.begin() ## turn on showtext text(1, 1, intToUtf8(c(82, 35821, 35328)), cex = 10, family = "fang") showtext.end() ## turn off showtext dev.off()
The use of
intToUtf8() is for convenience if you can’t view or input
Chinese characters. You can instead use
text(1, 1, "R语言", cex = 10, family = "fang")
This example should work fine on Windows. For other OS, you may not have
simfang.ttf font file, but there is no difficulty in using something
else. You can see the next section to learn details about how to load
a font with
Loading font is actually done by package sysfonts,
which is depended on by
The easiest way to load font into R is by calling
font.add(family, regular, ...),
family is the name that you give to that font (so that later you can
par(family = ...) to use this font in plotting), and
regular is the
path to the font file. Usually the font file will be located in some “standard”
directories in the system (for example on Windows it is typically C:/Windows/Fonts).
You can use
font.paths() to check the current search path or add a new one,
font.files() to list available font files in the search path.
Usually there are many free fonts that can be downloaded from the web and then used by
showtext, as the following example shows:
library(showtext) wd = setwd(tempdir()) download.file("http://fontpro.com/download-family.php?file=35701", "merienda-r.ttf", mode="wb") download.file("http://fontpro.com/download-family.php?file=35700", "merienda-b.ttf", mode="wb") font.add("merienda", regular = "merienda-r.ttf", bold = "merienda-b.ttf") setwd(wd) pdf("showtext-ex2.pdf", 7, 4) plot(1, type = "n", xlab = "", ylab = "") showtext.begin() par(family = "merienda") text(1, 1.2, "R can use this font!", cex = 2) text(1, 0.8, "And in Bold font face!", font = 2, cex = 2) showtext.end() dev.off()
In this case we add two font faces(regular and bold) with the family name
“merienda”, and use
font = 2 to select the bold font face (
font = 1 is
selected by default, which is the regular font face).
font.add() supports TrueType fonts(*.ttf/*.ttc) and
OpenType fonts(*.otf), but adding new
font type is trivial as long as FreeType supports it.
showtext includes an open source CJK font
WenQuanYi Micro Hei.
If you just want to show CJK text in your graph, you don’t need to add any
extra font at all.
The image created by bitmap graphics devices (
looks ugly because they don’t support anti-alias feature well. To produce
high-quality output, try to use the
CairoJPEG() devices from the
The internals of
Every graphics device in R implements some functions to draw specific graphical
line() to draw lines,
polygon() to draw polygons,
textUTF8() to show text, etc. What
showtext does is to override
their own text rendering functions and replace them by hooks provided in
that will further call the device’s
line() to draw the
This action is done only when you call
showtext.begin() and won’t modify the
graphics device if you call
showtext.end() to restore the original device functions back.