Using system fonts in R graphs

December 31, 2013
By

(This article was first published on Yixuan's Blog - R, and kindly contributed to R-bloggers)

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 extrafont,
and also from the Revolution blog.

Now, we have another choice: the showtext package.

showtext 0.2 has just been
submitted to CRAN.
Below is the introduction of this package excerpted from the
README.md file. In short,

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 pdf(),
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

Why pdf() doesn’t work and how showtext works

Let me explain a little bit about how pdf() works.

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 pdf() is
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.

In comparison, 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.

The Usage

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 showtext to draw the text
  • Plot
  • 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
the 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 showtext.

Loading font

Loading font is actually done by package sysfonts,
which is depended on by showtext.

The easiest way to load font into R is by calling font.add(family, regular, ...),
where family is the name that you give to that font (so that later you can
call 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,
and use 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).

At present font.add() supports TrueType fonts(*.ttf/*.ttc) and
OpenType fonts(*.otf), but adding new
font type is trivial as long as FreeType supports it.

Note that 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.

Known issues

The image created by bitmap graphics devices (png(), jpeg(), …)
looks ugly because they don’t support anti-alias feature well. To produce
high-quality output, try to use the CairoPNG() and CairoJPEG() devices from the
Cairo package.

The internals of showtext

Every graphics device in R implements some functions to draw specific graphical
elements, e.g., line() to draw lines, path() and polygon() to draw polygons,
text() or textUTF8() to show text, etc. What showtext does is to override
their own text rendering functions and replace them by hooks provided in showtext
that will further call the device’s path(), polygon() or line() to draw the
character glyphs.

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.

To leave a comment for the author, please follow the link and comment on their blog: Yixuan's Blog - R.

R-bloggers.com offers daily e-mail updates about R news and tutorials on topics such as: Data science, Big Data, R jobs, visualization (ggplot2, Boxplots, maps, animation), programming (RStudio, Sweave, LaTeX, SQL, Eclipse, git, hadoop, Web Scraping) statistics (regression, PCA, time series, trading) and more...



If you got this far, why not subscribe for updates from the site? Choose your flavor: e-mail, twitter, RSS, or facebook...

Comments are closed.

Search R-bloggers


Sponsors

Never miss an update!
Subscribe to R-bloggers to receive
e-mails with the latest R posts.
(You will not see this message again.)

Click here to close (This popup will not appear again)