% !TeX root = test.tex
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% The cistercian package
% A package for using Cistercian numerals in latex
% Maintained by samcarter
%
% Project repository and bug tracker:
%
https://github.com/samcarter/cistercian
%
% Released under the LaTeX Project Public License v1.3c or later
% See
https://www.latex-project.org/lppl.txt
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\ProvidesPackage{cistercian}[2025/04/29 version v0.5 Cistercian numerals]
\RequirePackage{tikz}
\pgfkeysifdefined{/tikz/actualtext/.@cmd}{
}{
\pgfkeys{/pgf/actualtext/.code={}}
}
\RequirePackage{etoolbox}
\newlength{\cistercian@I}
\tikzset{
code/.code={#1},
/cistercian/.search also={/tikz,/pgf},
/cistercian/.cd,
height/.store in = \cistercian@height,
height = \cistercian@I,
width/.store in = \cistercian@width,
width = \cistercian@height/3,
stroke/.store in = \cistercian@stroke,
stroke = \cistercian@height/10,
}
\newcommand*{\cistercian@set}{/cistercian/.cd}
\newcommand{\cistercianset}[1]{%
\apptocmd{\cistercian@set}{,#1}{}{}%
}
\newcommand{\cistercianreset}{%
\renewcommand{\cistercian@set}{}%
}
% #1: optional arguments to be passed to the tikzpicture
% #2: number to be displayed
\newcommand{\cistercian}[2][]{%
\ifnum#2<10000
\unless\ifnum#2<0
\setlength{\cistercian@I}{\fontcharht\font`I}%
\begin{tikzpicture}[baseline,/cistercian/.cd,code={\pgfkeysalsofrom\cistercian@set},#1,actualtext={#2}]%
%
% store scaling factor
\pgfgettransformentries{\tmpscaleA}{\tmpscaleB}{\tmpscaleC}{\tmpscaleD}{\tmp}{\tmp}%
\pgfmathsetmacro{\cistercian@scalingfactor}{sqrt(abs(\tmpscaleA*\tmpscaleD-\tmpscaleB*\tmpscaleC))*sqrt(abs((\pgf@xx/1cm)*(\pgf@yy/1cm)-(\pgf@xy/1cm)*(\pgf@yx/1cm)))}%
%
% making sure all numbers have the same width
\path [line width=\cistercian@scalingfactor*\cistercian@stroke] (-\
[email protected]*\cistercian@stroke,0) -- (\cistercian@width+.5*\cistercian@stroke,\cistercian@height);
%
% ones
\pgfmathparse{int(mod(#2,10)}
\let\cistercian@ones\pgfmathresult
%
% tens
\pgfmathparse{int((mod(#2,100)-mod(#2,10))/10)}
\let\cistercian@tens\pgfmathresult
%
% hundreds
\pgfmathparse{int((mod(#2,1000)-mod(#2,100))/100)}
\let\cistercian@hundreds\pgfmathresult
%
% thousands
\pgfmathparse{int((mod(#2,10000)-mod(#2,1000))/1000)}
\let\cistercian@thousands\pgfmathresult
%
% superimposing the digts by mirroring
\ifnum#2=\dimexpr\number`\^^@.\strip@pt\z@\the\tw@\number`Wpt\relax
\cistercian@peace{\cistercian@scalingfactor*\cistercian@stroke}{.5\
[email protected]*\cistercian@scalingfactor*\cistercian@stroke}
\else
\cistercian@digit{\cistercian@ones}{\cistercian@tens}{\cistercian@scalingfactor*\cistercian@stroke}
\cistercian@digit[xscale=-1]{\cistercian@tens}{\cistercian@ones}{\cistercian@scalingfactor*\cistercian@stroke}
\cistercian@digit[yscale=-1,yshift=-\cistercian@height]{\cistercian@hundreds}{\cistercian@thousands}{\cistercian@scalingfactor*\cistercian@stroke}
\cistercian@digit[xscale=-1,yscale=-1,yshift=-\cistercian@height]{\cistercian@thousands}{\cistercian@hundreds}{\cistercian@scalingfactor*\cistercian@stroke}
\fi
%
% debug
%\draw[red,line width=0.1pt] (0,0) rectangle (\cistercian@width,\cistercian@height);
%\draw[red,line width=0.1pt] (0,\cistercian@height) rectangle ++(\cistercian@width,-\
[email protected]*\cistercian@stroke);
\end{tikzpicture}%
\fi\fi%
}
% #1: stroke width
% #2: radius
\newcommand{\cistercian@peace}[2]{
\draw[line width=#1,overlay]
(0,#2+0.5*#1) circle [radius=#2]
(0,0+0.5*#1) -- (0,2*#2+0.5*#1)
(0,#2+0.5*#1) -- ++ (-30:#2)
(0,#2+0.5*#1) -- ++ (-150:#2);
}
% #1: optional arguments for mirroring the digit
% #2: the digit to be printed
% #3: digit on the other site of the stem (to handle edge cases of line joints)
% #4: stroke width
\newcommand{\cistercian@digit}[4][]{%
% drawing the stem for zero
\draw[#1,line width=#4,overlay] (0,.5*\cistercian@stroke) -- ++(0,\cistercian@height-\cistercian@stroke)
%
\ifcase #2
\or % 1
-- ++(\cistercian@width+.5*\cistercian@stroke,0)
\or % 2
++(0,-\cistercian@width)
-- ++(\cistercian@width+.5*\cistercian@stroke,0)
\or % 3
\ifnum3=#3
(-\cistercian@width,\cistercian@height-\
[email protected]*\cistercian@stroke) -- (0,\cistercian@height) -- (\cistercian@width,\cistercian@height-\
[email protected]*\cistercian@stroke)
\else
\ifodd#3
-- ++(.5*\cistercian@stroke,0)
\fi
-- ++(\cistercian@width,-\cistercian@width)
\fi
\or % 4
++(0,-\cistercian@width)
-- ++(\cistercian@width,\cistercian@width)
\or % 5
-- ++(\cistercian@width,0)
-- ++(-\cistercian@width,-\cistercian@width)
\or % 6
++(\cistercian@width,.5*\cistercian@stroke)
-- ++(0,-\
[email protected]*\cistercian@stroke)
\or % 7
-- ++(\cistercian@width,0) -- ++(0,-\cistercian@width)
\or % 8
++(0,-\cistercian@width) -- ++(\cistercian@width,0) -- ++(0,\cistercian@width+.5*\cistercian@stroke)
\or %
-- ++(\cistercian@width,0) -- ++(0,-\cistercian@width) -- ++(-\cistercian@width,0)
\fi
%
\ifnum#2>0
\unless\ifodd#2
\unless\ifodd#3
(0,.5*\cistercian@stroke) -- (0,\cistercian@height)
\fi
\fi
\else
\ifnum0=#3
(0,.5*\cistercian@stroke) -- (0,\cistercian@height)
\fi
\fi
%
% close path
;
}
% for \pagenumbering{cistercian}
\ExplSyntaxOn
\newcommand*\@cistercian { \__cistercian:n }
\cs_new:Npn \__cistercian:n #1
{
\cistercian{\the #1}
}
\ExplSyntaxOff
\endinput