Example
watermark

4  TikZ Figures

4.1 TODO:

  • Move tikzarabic filter YAML options to within arabicsupport section

4.2 Introduction

I sometimes need to use TikZ figures with Arabic text in my document. This chapter describes how to do that.

In order to render TikZ figures in Quarto we will use a Pandoc Lua filter. I have modified a Pandoc Lua filter that was originally published here: https://github.com/danmackinlay/quarto_tikz

The modified filter tikzarabic.lua is part of my arabic-support extension.

4.3 Filter options

The filter needs some options that I’ve set globally in _quarto.yml:

tikzarabic:
  cache: true
  format: svg
  embed_mode: link
  engine: lualatex
  scale_html: 1.27978125
  template_html: srctex/tikz-template-html.tex
  template_pdf: srctex/tikz-template-pdf.tex
  libgs: /usr/local/Cellar/ghostscript/10.04.0/lib/libgs.dylib

Despite being named tikzarabic you can use this filter for regular TikZ diagrams as well. There is an example at the end of this chapter.

There is also an official filter that handles TikZ (and other formats) here: https://github.com/pandoc-ext/diagram. But unfortunately, I wasn’t able to get it to work with Arabic text. Probably something I was doing incorrectly.

Here is an explanation of the options:

  • cache: Uses a cache on the system in order to not have to build the TikZ code for every render. When cache is enabled then, if you modify the TikZ code, the figure is rebuilt. But if you modify the template or the filter, then the figures don’t seem to be rebuilt. So in this case you may temporarily have to set cache to false in order to rebuild the figures. Default value: false.

  • format: SVG preserves vector information for optimal rendering. Only valid for HTML doc output. PDF doc output always uses PDF format for TikZ figures regardless of what is specified for the format field. Default value: svg.

  • embed_mode: Only affects HTML output. If set to link then the HTML includes the figure as a link. If set to inline then the HTML encodes the figure inline as ASCII text. Default value: inline.

  • engine: The Arabic typesetting I’m using within the figures uses the package arabluatex which needs the LuaTex engine. This is specified using the text lualatex. Ideally, I should use xelatex to be consistent with the rest of the document but I haven’t yet figured out how to do that. There may be some incompatibility between the babel package and TikZ which would need to be resolved. Default value: latex.

  • scale_html: For HTML output, we first create a .dvi file from the TikZ .tex and then convert the .dvi to the .svg file that will be included in the HTML. In the process of converting DVI to SVG, if the image needs to be scaled up or down, we can apply a scale factor using this parameter. This scale is applied as an argument to the utility dvisvgm that we use for DVI to SVG conversion. This option only affects HTML output. Default value: 1.

    We specify the value 1.27978125. This number has been arrived at using the following reasoning: The default font size for the Tex documentclass is 10pt. Inspecting the stylesheet for the this web page shows us that the body text font size is 17px. Using the ratio of 96px = 72.27pt, we calculate that we need to have a font size of 12.7978125pt. So we apply a scale factor of 1.27978125 to the default 10pt font size.

  • template_html: Common TikZ template code for HTML output. Here’s what I’m using in my srctex/tikz-template-html.tex:

    \RequirePackage{luatex85}
    \documentclass{article}
    \usepackage[luatex,active,tightpage]{preview}
    \usepackage{amsmath}
    \usepackage{tikz}
    \usepackage{xcolor}
    \definecolor{mydarkgray}{RGB}{52, 58, 64}
    
    
    \usepackage{fontspec}
    \defaultfontfeatures{Scale=MatchLowercase}
    \defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1}
    \setmainfont{Charis SIL}
    
    \usetikzlibrary{%s}
    \usetikzlibrary{matrix}
    \usepackage{arabluatex}
    \newfontfamily{\arabicfont}[Script=Arabic,Scale=1.2]{Vazirmatn-Regular}
    
    \begin{document}
    \begin{preview}
    \color{mydarkgray}
    %s
    \end{preview}
    \end{document}

    Note the use of the color mydarkgray to match the body text of the HTML theme. The color definition was obtained by inspecting this very page in a web browser, looking up the color specification from the stylesheet, and converting the HTML hexadecimal color code 343a40 to the decimal RGB values {52, 58, 64}.

    The Arabic font is then scaled by 1.2 with respect to the Roman text to match the rest of the text.

    The code block in the .qmd file will be inserted in the second %s’s location. Additional TikZ libraries may be inserted in the first %s’s location using the YAML option libraries.

    Default template:

    \documentclass[tikz]{standalone}
    \usepackage{amsmath}
    \usetikzlibrary{%s}
    \begin{document}
    %s
    \end{document}
    ]]
  • template_pdf: Common TikZ template code for PDF output. Here’s what I’m using in my srctex/tikz-template-pdf.tex:

    \RequirePackage{luatex85}
    \documentclass{article}
    \usepackage[luatex,active,tightpage]{preview}
    \usepackage{amsmath}
    \usepackage{tikz}
    
    \usepackage{fontspec}
    \defaultfontfeatures{Scale=MatchLowercase}
    \defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1}
    \setmainfont{Charis SIL}
    
    \usetikzlibrary{%s}
    \usetikzlibrary{matrix}
    \usepackage{arabluatex}
    \newfontfamily{\arabicfont}[Script=Arabic,Scale=1.0]{Vazirmatn-Light}
    
    \begin{document}
    \begin{preview}
    %s
    \end{preview}
    \end{document}

    It is identical to template_html except for:

    • a different weight for the Arabic font: “light” instead of “regular” to match the main document
    • the absence of the dark gray color for the text,
    • no scale applied to the Roman font.

    The default template is the same as the default for template_html.

  • libgs: In order to use this filter with svg format for HTML output, you need to make sure that the utlities dvisvgm and Ghostscript are installed on your system. This can be verified using the commands: which dvisvgm and which gs. If dvisvgm was not compiled with Ghostscript then you may need to link the location of the Ghostscript library on your system using the option libgs.

    Note that if you use Homebrew on MacOS to manage installation of the ghostscript utility, then, when it updates packages it will change the version number in the path and delete the old path. So then, if you don’t update the libgs field to point to the new path then your figures will start to look corrupted.

    Default value: "".

4.4 Example TikZ figure with Arabic text

Here is an example of a TikZ diagram with Arabic text:

Arabic text:
ٱَلْبَيْتُ كَبِيرٌ

TikZ Figure:

This is the source code for the figure in the source .qmd file:

```{.tikzarabic}
\usetikzlibrary{decorations.text, decorations.pathreplacing}
\begin{tikzpicture}[nodes={text depth=0.25ex,text height=2.0ex}]
\path [decoration={text effects along path,
  text=.\txarb{كَبِيرٌ} \txarb{ٱَلْبَيْتُ},
  text effects/.cd,
    path from text, text along path,
    group letters, word count=\w,
    every word/.style={name=word-\w, execute at begin node=\strut}},
  decorate] (0,0);

\draw [decoration={brace, mirror}, decorate]
  (word-1.south west) -- (word-1.south east)
    node [midway, rotate=90, anchor=south, left=0ex, align=left] 
      {\scriptsize predicate};

\draw [decoration={brace, mirror}, decorate]
  (word-2.south west) -- (word-2.south east)
    node [midway, rotate=90, anchor=south, left=0ex, align=left] 
      {\scriptsize subject};

\path (0,0) 
  node [midway, below=13.5ex, right=0ex, align=left] 
    {``The house is big.''};

\end{tikzpicture}
```

4.5 Overriding global options

If you wish to override any of the global parameters back to their default values, or to other values, you can do so inline using the comment-pipe (%%| option: value) format. Here is an example:

Source code:

```{.tikzarabic}
%%| embed_mode: inline
%%| engine: default
%%| template_html: default
%%| template_pdf: default
\begin{tikzpicture}[nodes={text depth=0.25ex,text height=2.0ex}]
\node[draw, circle] (A) at (0,0) {A};
\node[draw, circle] (B) at (2,2) {$\phi$};
\node[draw, circle] (C) at (4,0) {C};
\node[draw, circle] (seven) at (5,1) {888888};
\draw[->] (A) -- (B);
\draw[->] (B) -- (C);
\draw[->] (C) -- (A);
\end{tikzpicture}
```