---
title: "Introduction to gridmicrotex"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Introduction to gridmicrotex}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  dpi = 300,
  dev = "png"
)
```

## Quick start

`grid.latex()` draws LaTeX on the current page; `latex_grob()` returns it
as a grob.

```{r basic, fig.height=1, fig.width=2.4, out.width="45%"}
library(gridmicrotex)
library(grid)

grid.newpage()
grid.latex(r"($\frac{\textcolor{red}{-b} \pm \sqrt{b^2 - 4ac}}{2a}$)")
```

Write LaTeX in a raw string, `r"(...)"`, so backslashes need no doubling.

## Text and math

A string is read like a line of LaTeX text: math goes between `$...$` or
`\(...\)`, and a newline starts a new line. With `input_mode = "math"`
the whole string is math and text goes in `\text{}`. These two are the
same:

```{r modes, fig.height=1.2, fig.width=3.2, out.width="45%"}
grid.newpage()
grid.latex(r"(Famous: $E = mc^2$)",
           x = 0.05, y = 0.7, hjust = 0)
grid.latex(r"(\text{Famous: } E = mc^2)", input_mode = "math",
           x = 0.05, y = 0.3, hjust = 0)
```

`input_mode = "document"` reads a document body with paragraphs,
headings and displayed equations (see `vignette("documents")`).
`latex_options(input_mode = )` sets the default for the session.

Mistakes do not stop the drawing. One warning lists each problem with its
line and column, and an unknown command is drawn in red:

```{r malformed, fig.height=0.7, fig.width=5, out.width="55%"}
grid.newpage()
grid.latex(r"(Area $\pi r^2$, see \nosuchcommand{here})")
```

## Base graphics

Set `latex_options(device_math = TRUE)` and write `$...$` in any base
plot label:

```{r base-quick, fig.height=3.6, fig.width=6, out.width="70%"}
latex_options(device_math = TRUE)

plot(1:10, (1:10)^2,
     main = r"(Slope $\hat{\beta}_1 = \sum_{i=1}^{n} x_i^2$)",
     xlab = r"($x$)", ylab = r"($\frac{y}{2}$)")
text(3, 80, r"($\int_0^\infty e^{-x^2}\,dx$)", col = "steelblue")
```

```{r base-quick-off, include = FALSE}
latex_options(device_math = FALSE)
```

See `vignette("base-graphics")` for details.

## Examples

A coloured `array` with `\multicolumn`, `\rowcolor`, `\cellcolor`, a
custom column type and a nested matrix:

```{r showcase-table, fig.height = 3, fig.width = 8, out.width="70%"}
grid.newpage()
grid.latex(r"(
\newcolumntype{s}{>{\color{#1234B6}}c}
\begin{array}{|c|c|c|s|}
  \hline
  \rowcolor{Tan}\multicolumn{4}{|c|}{\textcolor{white}{\bold{\text{Table Head}}}}\\
  \hline
  \text{Matrix}&\multicolumn{2}{|c|}{\text{Multicolumns}}&\text{Font size commands}\\
  \hline
  \begin{pmatrix}
      \alpha_{11}&\cdots&\alpha_{1n}\\
      \hdotsfor{3}\\
      \alpha_{n1}&\cdots&\alpha_{nn}
  \end{pmatrix}
  &\large \text{Left}&\cellcolor{#00bde5}\small \textcolor{white}{\text{\bold{Right}}}
  &\small \text{small Small}\\
  \hline
  \multicolumn{4}{|c|}{\text{Table Foot}}\\
  \hline
\end{array}
)")
```

Assorted notation: `split` alignment, fraktur, stacked delimiters,
`\sideset`, extensible arrows, `\rotatebox` and `\reflectbox`:

```{r showcase-equation, fig.height = 9, fig.width = 9, out.width="70%"}
grid.newpage()
grid.latex(r"(
\definecolor{gris}{gray}{0.9}
\definecolor{noir}{rgb}{0,0,0}
\fatalIfCmdConflict{false}
\newcommand{\pa}{\left|}
\begin{array}{c}
  \LaTeX\\
  \begin{split}
      |I_2| &= \pa\int_0^T\psi(t)\left\{ u(a,t)-\int_{\gamma(t)}^a \frac{d\theta}{k} (\theta,t) \int_a^\theta c(\xi)
          u_t (\xi,t)\,d\xi\right\}dt\right|\\
      &\le C_6 \Bigg|\pa f \int_\Omega \pa\widetilde{S}^{-1,0}_{a,-}
          W_2(\Omega, \Gamma_1)\right|\ \right|\left| |u|\overset{\circ}{\to} W_2^{\widetilde{A}}(\Omega\Gamma_r,T)\right|\Bigg|\\
      &\\
      &\begin{pmatrix}
          \alpha&\beta&\gamma&\delta\\
          \aleph&\beth&\gimel&\daleth\\
          \mathfrak{A}&\mathfrak{B}&\mathfrak{C}&\mathfrak{D}\\
          \boldsymbol{\mathfrak{a}}&\boldsymbol{\mathfrak{b}}&\boldsymbol{\mathfrak{c}}&\boldsymbol{\mathfrak{d}}
      \end{pmatrix}
      \quad{(a+b)}^{\frac{n}{2}}=\sqrt{\sum_{k=0}^n\tbinom{n}{k}a^kb^{n-k}}\quad
          \Biggl(\biggl(\Bigl(\bigl(()\bigr)\Bigr)\biggr)\Biggr)\\
      &\forall\varepsilon\in\mathbb{R}_+^*\ \exists\eta>0\ |x-x_0|\leq\eta\Longrightarrow|f(x)-f(x_0)|\leq\varepsilon\\
      &\det
      \begin{bmatrix}
          a_{11}&a_{12}&\cdots&a_{1n}\\
          a_{21}&\ddots&&\vdots\\
          \vdots&&\ddots&\vdots\\
          a_{n1}&\cdots&\cdots&a_{nn}
      \end{bmatrix}
      \overset{\mathrm{def}}{=}\sum_{\sigma\in\mathfrak{S}_n}\varepsilon(\sigma)\prod_{k=1}^n a_{k\sigma(k)}\\
      &\Delta f(x,y)=\frac{\partial^2f}{\partial x^2}+\frac{\partial^2f}{\partial y^2}\qquad\qquad \fcolorbox{noir}{gris}
          {n!\underset{n\rightarrow+\infty}{\sim} {\left(\frac{n}{e}\right)}^n\sqrt{2\pi n}}\\
      &\sideset{_\alpha^\beta}{_\gamma^\delta}{
      \begin{pmatrix}
          a&b\\
          c&d
      \end{pmatrix}}
      \xrightarrow[T]{n\pm i-j}\sideset{^t}{}A\xleftarrow{\overrightarrow{u}\wedge\overrightarrow{v}}
          \underleftrightarrow{\iint_{\mathds{R}^2}e^{-\left(x^2+y^2\right)}\,\mathrm{d}x\mathrm{d}y}
  \end{split}\\
  \rotatebox{30}{\sum_{n=1}^{+\infty}}\quad\mbox{Mirror rorriM}\reflectbox{\mbox{Mirror rorriM}}
\end{array}
)", render_mode = "path")
```

## Placing a formula

`hjust` and `vjust` take numbers or names. `vjust = "baseline"` puts the
formula's baseline on `y`, so it lines up with text beside it:

```{r baseline-align, fig.height=1.1, fig.width=6, out.width="70%"}
grid.newpage()
y <- 0.5
grid.segments(unit(0, "npc"), unit(y, "npc"),
              unit(1, "npc"), unit(y, "npc"), gp = gpar(col = "grey80"))
grid.text("if ", x = 0.10, y = y, just = c(0, 0.5), gp = gpar(fontsize = 20))
grid.latex(r"($x \geq \sqrt{2\pi}$)",
           x = 0.22, y = y, hjust = "left", vjust = "baseline",
           gp = gpar(fontsize = 20))
grid.text(", then proceed.", x = 0.62, y = y, just = c(0, 0.5),
          gp = gpar(fontsize = 20))
```

### Named anchors

`\mark{name}` records a point inside a formula, and `grobMark()` returns
it as grid units, ready for an arrow or a callout:

```{r mark, fig.height=2.4, fig.width=5, out.width="70%"}
g <- latex_grob(r"($a^2 + b\mark{term}^2 \mark{equals}= c^2$)",
                x = 0.5, y = 0.4)
grid.newpage()
grid.draw(g)

mk_eq <- grobMark(g, "equals")
grid.segments(mk_eq$x, mk_eq$y + unit(15, "mm"),
              mk_eq$x, mk_eq$y + unit(3, "mm"),
              arrow = arrow(length = unit(2, "mm"), type = "closed"),
              gp = gpar(col = "red"))
grid.text("equals", x = mk_eq$x, y = mk_eq$y + unit(18, "mm"),
          gp = gpar(col = "red"))

mk_bsq <- grobMark(g, "term")
grid.segments(mk_bsq$x - unit(6, "mm"), mk_bsq$y - unit(15, "mm"),
              mk_bsq$x - unit(2, "mm"), mk_bsq$y - unit(3, "mm"),
              arrow = arrow(length = unit(2, "mm"), type = "closed"),
              gp = gpar(col = "blue"))
grid.text("b² term", x = mk_bsq$x - unit(7, "mm"),
          y = mk_bsq$y - unit(18, "mm"), just = "right",
          gp = gpar(col = "blue"))
```

## Display and text style

`$...$` sets a formula in text style, as in a paragraph; `$$...$$` sets
it in display style, with limits above and below. A label without
delimiters is set in text style. `tex_style` overrides this:

```{r style-options, fig.height=1.9, fig.width=6.5, out.width="100%"}
sum_expr <- r"(\sum_{i=1}^{n} \frac{x_i}{n})"
styles <- c("display", "text", "script", "scriptscript")
labels <- c('"display"  ($$...$$)', '"text"  ($...$)',
            '"script"', '"scriptscript"')

grid.newpage()
for (i in seq_along(styles)) {
  pushViewport(viewport(x = (i - 0.5) / 4, width = 1 / 4))
  grid.text(labels[i], y = 0.88, gp = gpar(cex = 0.75, fontface = "bold"))
  grid.latex(sum_expr, y = 0.42, input_mode = "math",
             tex_style = styles[i], gp = gpar(fontsize = 20))
  grid.rect(gp = gpar(col = "grey85", fill = NA))
  popViewport()
}
```

All four use the same font size. To change the style of part of a
formula, use `\displaystyle`, `\textstyle`, `\scriptstyle` or
`\scriptscriptstyle`.

## Line wrapping

`max_width`, in big points, wraps a label over several lines.
`justify = TRUE` fills every line but the last, and
`line_break = "optimal"` balances the breaks across the paragraph:

```{r wrap, fig.height = 2, fig.width = 4, out.width = "65%"}
prose <- paste(rep(
  r"(The quick brown fox jumps over the lazy dog, and $x^2$ too.)", 3),
  collapse = " ")

grid.newpage()
pushViewport(viewport(layout = grid.layout(2, 1)))
pushViewport(viewport(layout.pos.row = 1))
grid.text("ragged (default)", x = 0.02, y = 0.98, hjust = 0, vjust = 1,
          gp = gpar(col = "grey40"))
grid.latex(prose, x = 0.02, y = 0.78, hjust = 0, vjust = 1,
           max_width = 3.6 * 72, gp = gpar(fontsize = 11))
popViewport()
pushViewport(viewport(layout.pos.row = 2))
grid.text("justified + optimal", x = 0.02, y = 0.98, hjust = 0, vjust = 1,
          gp = gpar(col = "grey40"))
grid.latex(prose, x = 0.02, y = 0.78, hjust = 0, vjust = 1,
           max_width = 3.6 * 72, justify = TRUE, line_break = "optimal",
           gp = gpar(fontsize = 11))
popViewport(2)
```

Words are not hyphenated. Mark where one may break with `\-`, as in
`in\-ter\-na\-tion\-al`.

## Images

`\includegraphics` draws a PNG, JPEG or SVG file. Size it with `width`,
`height` or `scale`, and rotate it with `angle`. The extension may be
left off, and `\graphicspath{{figs/}}` adds a folder to search.

```{r img-basic, fig.height = 1.6, fig.width = 4, out.width = "60%"}
fig <- tempfile(fileext = ".svg")
svglite::svglite(fig, width = 2, height = 1.2)
grid.newpage()
grid.circle(r = 0.35, gp = gpar(fill = "steelblue", col = NA))
dev.off()

grid.newpage()
grid.latex(sprintf(r"(before \includegraphics[width=1in]{%s} after)", fig),
           gp = gpar(fontsize = 20))
```

An inline image sits on the baseline; `\raisebox` moves it. A `\caption`
is drawn where it is written. To centre a figure and its caption, put
them in a one-column `array`:

```{r img-caption, fig.height = 1.4, fig.width = 3, out.width = "45%"}
logo <- system.file("img", "Rlogo.png", package = "png")
grid.newpage()
grid.latex(sprintf(r"(\begin{array}{c}
  \includegraphics[width=0.6in]{%s}\\
  \caption{Figure 1: the R logo}
\end{array})", logo), gp = gpar(fontsize = 11))
```

Prefer SVG, which stays sharp at any size. A PNG or JPEG warns when it is
shown below 150 dpi. PDF and EPS files are not supported.

## Fonts

Two math fonts are included:

| Alias | Font | Style | Pairs with |
|-------|------|-------|------------|
| `"lete"` (default) | Lete Sans Math | Sans-serif | `fontfamily = "sans"` |
| `"stix"` | STIX Two Math | Serif | `fontfamily = "serif"` |

Choose one with `math_font`, or for the session with
`latex_options(math_font = )`. Text follows `gp$fontfamily`:

```{r fonts, fig.height=1.5, fig.width=3.4, out.width="60%"}
formula <- r"(Theorem: $\int_0^1 f(x)\,dx \geq 0$)"

grid.newpage()
pushViewport(viewport(layout = grid.layout(2, 1)))
pushViewport(viewport(layout.pos.row = 1))
grid.latex(formula, gp = gpar(fontfamily = "sans"))
upViewport()
pushViewport(viewport(layout.pos.row = 2))
grid.latex(formula, math_font = "stix",
           gp = gpar(fontfamily = "serif"))
upViewport(2)
```

Any font R can use works for text, including CJK and right-to-left
scripts:

```{r cjk, fig.height=1, fig.width=5, out.width="55%", dev = "ragg_png", dev.args = list(), purl = FALSE}
grid.newpage()
grid.latex(r"(如果 $x > 0$ 则 $y = x^2$)",
           gp = gpar(fontfamily = "sans"))
```

`\textsf{}` and `\texttt{}` set text in the sans and mono fonts, and
`\textrm{}` returns to `gp$fontfamily`:

```{r textrm, fig.height=0.8, fig.width=4.5, out.width="85%", dev = "ragg_png", dev.args = list()}
grid.newpage()
grid.latex(
  r"(\textsf{sans \textrm{body} sans} \quad \texttt{mono})",
  gp = gpar(fontfamily = "serif")
)
```

### Your own fonts

`load_font()` names a font file, or an installed family, once, and loads
an OpenType math font for `math_font` the same way. The name
then works wherever a font is named: in `gp`, in `latex_options()`
(`main_font`, `sans_font`, `mono_font`) and in the LaTeX itself, with the
commands of fontspec and unicode-math (`\setmainfont`, `\setsansfont`,
`\setmonofont`, `\setmathfont`, `\fontspec`, `\newfontfamily`) and
`\fontfamily{...}\selectfont`, which also reads LaTeX's family codes such as
`ppl` for Palatino.

```{r load-font, fig.height=0.8, fig.width=4.5, out.width="85%"}
# A font file of your own, here the bundled Lete Sans Math
otf <- system.file("fonts", "LeteSansMath.otf", package = "gridmicrotex")
load_font(otf, name = "My Font", bold = otf)

grid.newpage()
grid.latex(r"(\setmainfont{My Font} body, \textbf{bold} and
          {\fontspec{STIX Two Math} another font})")
```

Text in a loaded font is drawn from its file on every device, `pdf()`
included. `bold` and `italic` are the files of those faces, so `\textbf` and
`\textit` use the real design. `available_fonts()` lists what is loaded.

An installed family is loaded by its name; its bold and italic faces are found
on their own. The families installed differ from one system to the next, so
this chunk is not run:

```{r load-installed-font, eval=FALSE}
unique(systemfonts::system_fonts()$family)   # what is installed

load_font("Georgia")                          # registered as "Georgia"
latex_options(main_font = "Georgia")
grid.latex(r"(Text in \textbf{Georgia} and $x^2$)")
```

## Devices

By default glyphs are drawn as text, so PDF and SVG output can be
selected and searched. This needs `ragg`, `svglite` or `cairo_pdf()`; on
other devices, such as `pdf()`, glyphs are drawn as outlines with a
warning. `render_mode = "path"` always draws outlines: it works on every
device, but the text cannot be selected.

If the default device on Windows or macOS warns `font family not found`,
use `ragg::agg_png()` instead.

`showtext::showtext_auto()` turns all text into outlines, formulas
included. Turn it off with `showtext::showtext_auto(FALSE)`.

## Utilities

`latex_dims()` measures a formula:

```{r dims}
latex_dims(r"(\frac{a}{b})", gp = gpar(fontsize = 20))
```

`latex_options()` sets defaults for the session; arguments given in a
call always win:

```{r options, eval=FALSE}
latex_options(math_font = "stix")
latex_options()        # show the current settings
reset_latex_options()  # back to the defaults
```

`define_macro()` adds a shorthand for every later label:

```{r macros, fig.height=0.7, fig.width=3, out.width="50%"}
define_macro("RR", r"(\mathbb{R})")
define_macro("eps", r"(\varepsilon)")

grid.newpage()
grid.latex(r"($\forall \eps > 0, \eps \in \RR$)")

clear_macros()
```

A label can also define its own, with `\newcommand` or `\def`. These last
for that label only:

```{r def-inline, fig.height=0.7, fig.width=4, out.width="60%"}
grid.newpage()
grid.latex(
  r"(\def\norm#1{\left\lVert #1 \right\rVert}
      $\norm{\vec{v}} = \sqrt{\langle \vec{v}, \vec{v} \rangle}$)"
)
```

`debug = TRUE` draws the bounding box and baseline:

```{r debug, fig.height=1, fig.width=3, out.width="60%"}
grid.newpage()
grid.latex(r"($x^{2} + y_{i}$)", debug = TRUE)
```

## Diagrams

tikz-cd's `tikzcd` and amscd's `CD` draw commutative diagrams: objects in
a grid joined by arrows. An arrow is written in the cell it leaves, with
the direction it goes (`r`, `d`, `dr`, `rr`, ...), a label in quotes (a
prime puts it on the other side), and a style:

```{r tikzcd, fig.height = 1.6, fig.width = 2.6, out.width = "40%"}
sq <- r"(\begin{tikzcd}
A \arrow[r, "f"] \arrow[d, "g"'] \arrow[dr, dashed] & B \arrow[d, "h"] \\
C \arrow[r, hook, "k"'] & D
\end{tikzcd})"
grid.newpage()
grid.latex(sq, x = 0.5, y = 0.5, gp = gpar(fontsize = 14))
```

Styles include `hook`, `tail`, `two heads`, `mapsto`, `dashed`, `dotted`,
`Rightarrow`, `equal`, `harpoon`, `squiggly`, `bend left`, `shift right`,
`crossing over`, `phantom` and a colour name; labels take
`description`, `near start` and `near end`; and `row sep` and `column sep`
set the spacing. `CD` writes its arrows between the objects instead:

```{r cd, fig.height = 1.6, fig.width = 5.2, out.width = "70%"}
cd <- r"(\begin{CD}
A @>f>> B \\
@VgVV @VVhV \\
C @>>k> D
\end{CD})"
bent <- r"(\begin{tikzcd}[column sep=large]
A \arrow[r, "f", bend left] \arrow[r, "g"', bend right]
  & B \arrow[r, two heads, mapsto] & C
\end{tikzcd})"
grid.newpage()
grid.latex(cd, x = 0.2, y = 0.5, gp = gpar(fontsize = 14))
grid.latex(bent, x = 0.68, y = 0.5, gp = gpar(fontsize = 14))
```

## Pasting LaTeX

Tables from `knitr::kable(format = "latex")`, kableExtra, `xtable`, gt
and tinytable can be pasted unchanged:

```{r pasted, fig.height = 1.1, fig.width = 3.2, out.width = "55%"}
snippet <- r"(
% latex table generated by kable()
\begin{table}[ht]
\centering
\caption{Model coefficients}
\begin{tabular}{lrr}
\toprule
Term & Estimate & \emph{p} \\
\midrule
Intercept & 2.14 & 0.003 \\
Slope & 0.42 & 0.001 \\
\bottomrule
\end{tabular}
\end{table}
)"

grid.newpage()
grid.latex(snippet, gp = gpar(fontsize = 11))
```

A table is set to the `max_width` it is given, so `kable(booktabs = TRUE)`
and a full-width kableExtra or gt table can be drawn as they are:

```{r kable, fig.height = 1.5, fig.width = 4.5, out.width = "65%"}
tab <- knitr::kable(head(mtcars[, 1:4], 3), format = "latex",
                    booktabs = TRUE, digits = 1)
grid.newpage()
grid.latex(as.character(tab), input_mode = "document", max_width = 4 * 72,
           x = 0.05, y = 0.95, hjust = 0, vjust = 1, gp = gpar(fontsize = 11))
```

tinytable's output is read as well:

```{r tinytable, fig.height = 1.5, fig.width = 4.5, out.width = "65%"}
tt <- r"(\begin{table}
\centering
\begin{tblr}{
colspec={Q[]Q[r]Q[r]},
hline{1,3}={1-3}{solid, black, 0.08em},
hline{2}={1-3}{solid, black, 0.05em},
row{2}={}{font=\bfseries, bg=yellow},
}
Term & Estimate & p \\
Intercept & 2.14 & 0.003 \\
Slope & 0.42 & 0.001 \\
\end{tblr}
\end{table})"
grid.newpage()
grid.latex(tt, input_mode = "document", max_width = 4 * 72,
           x = 0.05, y = 0.95, hjust = 0, vjust = 1, gp = gpar(fontsize = 11))
```

## What is supported

Every function on KaTeX's lists of supported functions is drawn, and more. A list of
them, in KaTeX's order, with how each is drawn, is
on the package website as `supported-functions.pdf`. `source(system.file(
"supported/build.R", package = "gridmicrotex"))` and `build_supported()` write
it, and its LaTeX file, wherever you ask.

## Not supported

- Pages: `\pageref` draws `??` and `\cite` draws `[?]`.
- Automatic hyphenation, and TikZ beyond `tikz-cd` diagrams.
- `\usepackage` loads nothing; every supported command is built in.
- A formula between two right-to-left words is not reordered.
