by Paul Murrell http://orcid.org/0000-0002-3224-8858
Version 1: Tuesday 22 December 2020
This document
by Paul
Murrell is licensed under a Creative
Commons Attribution 4.0 International License.
The 'dvir' package for R is limited in that it is only known to work on an (Ubuntu) Linux distribution with (at least) a full TeX installation. Unfortunately, not even that is true for recent stable Linux releases, like Ubuntu 20.04, because of a dependence on Type 1 fonts. This report describes an update to the 'dvir' package, plus some guidelines on avoiding Type 1 fonts, so that 'dvir' will work on recent stable Linux distributions (or at least Ubuntu 20.04).
The 'dvir' package (Murrell, 2020c, Murrell, 2018, Murrell, 2020b, Murrell, 2020a) provides functions for rendering TeX output on R graphics devices. For example, the following code renders a simple TeX mathematical expression in R graphics (on Ubuntu 18.04).
library(dvir) grid.latex("$x - \\mu$")
Unfortunately, not even that simple example works on recent stable Linux distributions. For example, the output below shows what 'dvir' (version 0.3-0) produces on Ubuntu 20.04.
library(dvir, lib.loc="/opt/R/dvir/version-0.3-0") grid.latex("$x - \\mu$")
There are two steps involved in the solution to this problem:
The following code provides a simple demonstration.
First, we load version 0.3-1 of the 'dvir' package.
Then, we need to complicate the call to
grid.latex
a little bit.
The core TeX code is still just a simple equation, but
we specify a preamble that loads the unicode-math
package (Robertson et al., 2019) and we select LuaTeX as the TeX engine.
This means that the TeX engine will use the Latin Modern Math
font (Jackowski et al., 2014),
which is an Open Type font, and the resulting output
is back to what we would like.
library(dvir, lib.loc="/opt/R/dvir/version-0.3-1") preamble <- " \\documentclass[12pt]{standalone} \\usepackage{unicode-math} \\begin{document} " grid.latex("$x - \\mu$", preamble=preamble, engine=lualatexEngine)
This section explains the problem, and the solution, in more detail.
The following output shows the relevant part of the DVI output that is generated by the default LaTeX engine on Ubuntu 20.04.
dviFile <- typeset("$x - \\mu$") dvi <- readDVI(dviFile)
fnt_def_1 fontnum=27, checksum=-1209964637, scale=786432, design=786432, fontname=cmmi12 fnt_num_27 set_char_120 'x' w3 b=174760 fnt_def_1 fontnum=30, checksum=555887770, scale=786432, design=655360, fontname=cmsy10 fnt_num_30 set_char_0 '' w0 fnt_num_27 set_char_22 ''
The fnt_def_1
operations
show that LaTeX has used cmmi12
(Computer Modern Math
Italic) and cmsy10
(Computer Modern Symbol) fonts to
typeset the equation. These are Type 1 (.pfb
)
fonts.
kpsewhich -format=.pfb cmmi12
/usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi12.pfb
kpsewhich -format=.pfb cmsy10
/usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy10.pfb
The problem with that is that Ubuntu 20.04 has a Pango (Taylor et al., 2020) version above 1.44.
grSoftVersion()
cairo cairoFT pango libpng "1.16.0" "" "1.44.7" "1.6.37" jpeg libtiff "8.0" "LIBTIFF, Version 4.1.0"
The problem with that is that Pango versions above 1.44 have abandoned
support for Type 1 fonts and the problem with that is that R's Cairo-based
graphics devices make use of Pango for typesetting text, so when
grid.latex
attempts to draw text using the same Type 1
fonts that the TeX engine used, on the default (Linux) graphics device
(a Cairo X11 window or a Cairo PNG file), it fails. The result is
the boxes containing hexadecimal values that indicate missing glyphs.
The problem is limited to Cairo-based graphics devices, so a relatively simple workaround is to draw on a PDF or PostScript graphics device instead. The following code demonstrates that this workaround works on Ubuntu 20.04 even with the old version of 'dvir' (0.3-0).
library(dvir, lib.loc="/opt/R/dvir/version-0.3-0") dg <- dviGrob(dvi) pdf("workaround.pdf", width=2, height=1) grid.draw(dg) dev.off() embedFonts("workaround.pdf", outfile="workaround-embed.pdf", fontpaths=fontPaths(dg))
If we want to use the Cairo-based graphics devices on a recent stable Linux, we must avoid Type 1 fonts. This means that we must make sure that the TeX engine does not use Type 1 fonts because 'dvir', by design, uses exactly the same fonts that the TeX engine uses.
To demonstrate the problem again, the following code shows that, even with simple text, the default LaTeX engine produces an undesirable result (on Ubuntu 20.04, on a Cairo-based device, because it uses Type 1 fonts).
library(dvir, lib.loc="/opt/R/dvir/version-0.3-0")
grid.latex("Test")
One easy way to avoid Type 1 fonts is to use the LuaTeX engine, rather than the default LaTeX engine, because LuaTeX makes it easy to select different fonts. Then it is just a matter of selecting an Open Type or True Type font in the TeX code.
For a standard Computer Modern look, the lmodern
package (Harders, 2020)
automatically uses Latin Modern Roman
(Jackowski et al., 2020) as the default
(Open Type) font.
The following code shows that using the LuaTeX engine (and version 0.3-1
of 'dvir') and loading the
lmodern
package fixes the problem (because we are
now using an Open Type font; Latin Modern Roman).
library(dvir, lib.loc="/opt/R/dvir/version-0.3-1")
preamble <- " \\documentclass[12pt]{standalone} \\usepackage{lmodern} \\begin{document} " grid.latex("Test", preamble=preamble, engine=lualatexEngine)
The following code repeats the code from
The solution Section. This shows that using the
LuaTeX engine and loading the unicode-math
package, which automatically loads the Latin Modern Math (Open Type) font
for TeX math mode, fixes the problem for a simple equation.
library(dvir, lib.loc="/opt/R/dvir/version-0.3-1")
preamble <- " \\documentclass[12pt]{standalone} \\usepackage{unicode-math} \\begin{document} " grid.latex("$x - \\mu$", preamble=preamble, engine=lualatexEngine)
In addition to making sure that the TeX engine uses an Open Type or True Type font, we also need to use the updated version of 'dvir' (0.3-1).
This new version contains two important changes.
First of all, 'dvir' now makes use of the 'systemfonts' package
(Pedersen et al., 2020)
to get information about installed fonts.
This is because the systemfonts::system_fonts
function
can tell us about Open Type fonts.
Previous versions of 'dvir' made use of the
fonttable
function from the 'extrafont' package
(Chang, 2014),
but that can only tell us
about True Type fonts.
One complication is the fact that
system_fonts
does not include information about
.afm
files (while fonttable
does),
for the very good reason that Open Type fonts do not
have .afm
files. Only Type 1 fonts have .afm
files, which contain metric information about the glyphs in the font.
R graphics makes use of .afm
files when drawing to a
PDF or PostScript device. The 'extrafont' package actually generates
.afm
files for True Type fonts (so that they can be used
on PDF and PostScript devices).
However, we are interested here in using Open Type fonts on Cairo-based
devices, so the lack of .afm
information is not a problem.
The 'dvir' package uses TTX (van Rossum et al., 2020)
to extract metric information from the
Open Type font.
Using Open Type fonts on PDF and PostScript devices
is still an issue, but we will leave that for another day.
The second important change in 'dvir' version 0.3-1 involves
the support of set_char3
operations in DVI files.
These operations specify a character to draw as a 3-byte value.
Previously, 'dvir' has assumed that these operations only
represent non-UNICODE glyphs in a font (where the first byte is
0F
; see Murrell, 2020b
for details).
This assumption is horribly exposed by the simple
math equation example (when we use an Open Type font).
The following output shows the relevant DVI
code generated by the LuaTeX engine using the unicode-math
package.
library(dvir, lib.loc="/opt/R/dvir/version-0.3-1")
preamble <- " \\documentclass[12pt]{standalone} \\usepackage{unicode-math} \\begin{document} " dviFile <- typeset("$x - \\mu$", preamble=preamble, engine=lualatexEngine) dvi <- readDVI(dviFile)
fnt_def_1 fontnum=29, checksum=0, scale=786432, design=655360, fontname=[latinmodern-math.otf]:mode=base;script=math;language=dflt; fnt_num_29 set_char3 01 d4 65 right3 b=174744 set_char2 22 12 right3 b=174744 set_char3 01 d7 07
This shows that both the 'x' and the mu characters are
represented by set_char3
operations
(01 d4 65
and 01 d7 07
).
These specify the character to draw as
UNICODE code points in UTF-32 encoding (with the first byte
assumed to be zero).
Version 0.3-1 of 'dvir' now handles set_char3
operations of this type.
When using 'dvir' on a recent stable Linux, like Ubuntu 20.04, use the LuaTeX engine, write TeX code that selects an Open Type or True Type font, and use 'dvir' version 0.3-1 or higher.
The examples and discussion in this document relate to version 0.3-1 of the 'dvir' package.
This report was generated within a Docker container (see the Resources section below).
Murrell, P. (2020). "Letting Go of Type 1 Fonts" Technical Report 2020-06, Department of Statistics, The University of Auckland. version 1. [ bib | DOI | http ]
This document
by Paul
Murrell is licensed under a Creative
Commons Attribution 4.0 International License.