3

Suppose that I have the following XeLaTeX document:

\documentclass{article}
\usepackage{fontspec}
\setmainfont{Arial}
\begin{document}
Proin quis (tortor) orci. Etiam at risus et $(a + b)x$.
\end{document}

Is there a way to globally set, for example, the font Georgia for just the parentheses?

A similar thing could be done in the math mode with unicode-math. For example,

\documentclass{article}
\usepackage{fontspec}
\usepackage{unicode-math}
\setmathfont[range="0028]{Georgia}
\setmainfont{Arial}
\begin{document}
Proin quis (tortor) orci. Etiam at risus et $(a + b)x$.
\end{document}

The left parenthesis is in Georgia

Possibly related: Font selection in XeTeX for specific characters

Taiki
  • 506

1 Answers1

5

You can do this using XeTeXinterchartoks to insert the font change between characters of defined classes. I've adapted the code here from the replace-numbers.sty which is part of xelatex.

Unfortunately the XeTeX documentation on this is a bit out of date, and the character class of the boundaries has been changed to 4095. This is set to \e@alloc@intercharclass@top in the LaTeX kernel, so I've used this instead of a hard coded number. Thanks to the experts in chat for explaining this change.

In the example below I've added a \color{red} to the code to show the change clearly. This obviously should be removed for your actual use case.

% !TEX TS-program = xelatex
\documentclass{article}
\usepackage{xcolor}
\usepackage{fontspec}
\setmainfont{Linux Libertine O}
\newfontfamily\parenfont{Linux Biolinum O}
\makeatletter
\XeTeXinterchartokenstate=1
\chardef\CharNormal=0
\ifx\e@alloc@intercharclass@top\@undefined
\chardef\CharBound=255
\else
\chardef\CharBound=\e@alloc@intercharclass@top
\fi
\newXeTeXintercharclass\CharParens
\XeTeXcharclass`(=\CharParens
\XeTeXcharclass`)=\CharParens
\newtoks\TokSetfont
\TokSetfont={\begingroup\parenfont\color{red}} % remove \color{red} for actual use
\XeTeXinterchartoks\CharNormal\CharParens=\TokSetfont
\XeTeXinterchartoks\CharBound\CharParens=\TokSetfont
\XeTeXinterchartoks\CharParens\CharNormal={\endgroup}
\XeTeXinterchartoks\CharParens\CharBound={\endgroup}
\makeatother
\begin{document}
Proin quis (tortor) orci. Etiam at risus et $(a + b)x$.
\end{document}

output of code

Problems with this code This code checks for older versions of the latex kernel, and sets the boundary char class appropriately for that. However, there was one version of the kernel released in which \e@alloc@intercharclass@top was not defined although the char class was changed. If the above code doesn't run, try replacing the following code:

\ifx\e@alloc@intercharclass@top\@undefined
\chardef\CharBound=255
\else
\chardef\CharBound=\e@alloc@intercharclass@top
\fi

with this:

\chardef\CharBound=4095
Alan Munn
  • 218,180
  • I've got the following error running your example: Extra \endgroup. <XeTeXinterchartoks> \endgroup. – Taiki Sep 28 '16 at 17:15
  • 1
    It seems that you have the version of the latex kernel that lacked \e@alloc@intercharclass@top, but in which the character class of the boundary is 4095. I'll add some comments about that case. – Alan Munn Sep 28 '16 at 17:37
  • It works perfectly. Thank you very much! By the way, what do you mean by 'boundaries' in 'the character class of the boundaries'? – Taiki Sep 28 '16 at 18:17
  • 1
    @Taiki The boundary is anything between a string of characters. In the output of this document it looks like a space, but in reality it could be a box or a kern or glue or math and possibly some other elements. – Alan Munn Sep 28 '16 at 19:20