[Tex/LaTex] Using a different font for digits in text mode

fontsfontspecxetex

I am writing a document for which I would like to use a main font, let's call it myfont, which I have as several .otf files. To do so, I use XeTeX along with the fontspec package and the setmainfont command :

\usepackage{fontspec}
\setmainfont[Mapping=tex-text,
  BoldFont={myfont-bold.otf}, 
  ItalicFont={myfont-italic.otf},
  BoldItalicFont={myfont-bolditalic.otf}
]{myfont.otf}

The problem I have with myfont is that I don't like the digits. Therefore, I'd like to use another font, but only for digits. It could be possible if the setmainfont command had a numbers option, which it doesn't.
I would also like to precise that the font does not have support for lined digits, and only comes with Old Style.

The way I see it, there would be two ways to do so :

1/ Make all digits use the math font

If I could make every digit call the math font, there would be no problem, as the math font digits look alright. The main problem being that I have no idea if and how this could be done.

2/ Substitute characters manually

This is what is suggested by two resources I have found :
here and here – the latter referencing the former. Their solution was to use the fontspec package and to manually swap characters using :

\usepackage{fontspec}
\XeTeXinterchartokenstate=1
\chardef\CharNormal=0
\makeatletter
% Test for old and new versions of the latex kernel
\ifx\e@alloc@intercharclass@top\@undefined
    \chardef\CharBound=255
\else
    \chardef\CharBound=\e@alloc@intercharclass@top
\fi
\makeatother
\newXeTeXintercharclass\CharNumbers
\XeTeXcharclass`0=\CharNumbers
\XeTeXcharclass`1=\CharNumbers
\XeTeXcharclass`2=\CharNumbers
\XeTeXcharclass`3=\CharNumbers
\XeTeXcharclass`4=\CharNumbers
\XeTeXcharclass`5=\CharNumbers
\XeTeXcharclass`6=\CharNumbers
\XeTeXcharclass`7=\CharNumbers
\XeTeXcharclass`8=\CharNumbers
\XeTeXcharclass`9=\CharNumbers
\newtoks\TokSetfont
\TokSetfont={\begingroup\fontspec{Latin Modern Mono}}
\XeTeXinterchartoks\CharNormal\CharNumbers=\TokSetfont
\XeTeXinterchartoks\CharBound\CharNumbers=\TokSetfont
\XeTeXinterchartoks\CharNumbers\CharNormal={\endgroup}
\XeTeXinterchartoks\CharNumbers\CharBound={\endgroup}

The problem with this solution is that it does not seem to work ; it makes XeLaTeX compilation extremely slow, returning memory errors, and in the end the digits stay unchanged. The original solution was given in this answer, and as comments suggest, an infinite loop appears to be running.

Since the posts are rather old, and the solutions do not seem to work anymore, I figured I would ask again if anyone had an idea about how to change the main font for digits only. I am fully aware that this is an extremely unimportant thing to do, but still : any ideas ?

[EDIT] For convenience, a minimal working example with free fonts :

% !TeX program = xelatex
\documentclass{article}

\usepackage{fontspec}
\setmainfont[
    BoldFont={Georgia Bold}, 
    ItalicFont={Georgia Italic},
    BoldItalicFont={Georgia Bold Italic},
    SmallCapsFont={Latin Modern Roman Caps}
    ]{Linux Libertine O}

\begin{document}

Everything \textbf{just} \textsc{Works}, \\
but I don't like this ``1''

\end{document}

Best Answer

The bottleneck is using \fontspec. Rather declare a new font family, so font allocation is not redone at each start of a run of digits.

\documentclass{article}
\usepackage{fontspec}

\setmainfont{TeX Gyre Termes}
\newfontfamily{\digits}{TeX Gyre Heros}

\XeTeXinterchartokenstate=1
\chardef\CharNormal=0
\makeatletter
% Test for old and new versions of the latex kernel
\ifx\e@alloc@intercharclass@top\@undefined
    \chardef\CharBound=255
\else
    \chardef\CharBound=\e@alloc@intercharclass@top
\fi
\makeatother
\newXeTeXintercharclass\CharNumbers
\XeTeXcharclass`0=\CharNumbers
\XeTeXcharclass`1=\CharNumbers
\XeTeXcharclass`2=\CharNumbers
\XeTeXcharclass`3=\CharNumbers
\XeTeXcharclass`4=\CharNumbers
\XeTeXcharclass`5=\CharNumbers
\XeTeXcharclass`6=\CharNumbers
\XeTeXcharclass`7=\CharNumbers
\XeTeXcharclass`8=\CharNumbers
\XeTeXcharclass`9=\CharNumbers

\XeTeXinterchartoks\CharNormal\CharNumbers={\begingroup\digits}
\XeTeXinterchartoks\CharBound\CharNumbers={\begingroup\digits}
\XeTeXinterchartoks\CharNumbers\CharNormal={\endgroup}
\XeTeXinterchartoks\CharNumbers\CharBound={\endgroup}

\begin{document}

\count255=0

\loop\ifnum\count255<1000
\advance\count255 1
Text 123 text1text\endgraf
123\endgraf
\repeat

\end{document}

I tried these 2000 paragraphs with and without the interchar tokens and the compilation time is comparable.

enter image description here