Macro returning a length depending on current chapter

I am writing a document using scrbook and I have defined a custom chapter style where I draw a large chapter number using tikz:

\renewcommand*{\chapterformat}{%
\begin{tikzpicture}[remember picture, overlay]
\node[anchor=south east, yshift=1.2cm, xshift=\textwidth,
inner sep=0, outer sep=0]{%
\fontsize{10cm}{10cm}\selectfont%
\textcolor{laccentcolor}{\thechapter}%
};
% alignment line
\draw[thin] (current page text area.north east)
-- (current page text area.south east);
\end{tikzpicture}%
}


The chapter number is supposed to align to the right of the text area, but it doesn't because of the whitespace around the number that is part of the character:

The distance to the right border is different for each number. To achieve perfect alignment I would like to adjust the positioning of the chapter number on a per-chapter basis. My idea to achieve this was to define a command that returns a different length depending on the current value of \thechapter, and then use this command to define the xshift of the chapter number:

\newcommand*{\chapteroffset}{%
\IfEndWith{\thechapter}{1}{\textwidth+15mm}{%
\IfEndWith{\thechapter}{2}{\textwidth+5mm}{%
\IfEndWith{\thechapter}{3}{\textwidth+6mm}{%
\textwidth+0mm%
}}}%
}

\renewcommand*{\chapterformat}{%
\begin{tikzpicture}[remember picture, overlay]
\node[anchor=south east, yshift=1.2cm, xshift=\chapteroffset,
inner sep=0, outer sep=0]{%
\fontsize{10cm}{10cm}\selectfont%
\textcolor{laccentcolor}{\thechapter}%
};
% alignment line
\draw[thin] (current page text area.north east)
-- (current page text area.south east);
\end{tikzpicture}%
}


I've tried multiple different ways to achieve this, but all of them until now have resulted in some kind of endless loop where my document doesn't finish building. I suspect the reason is that I am not using the right way to return a dimension from an if expression.

How can I return a dimension from a macro that changes with the current chapter? Mind that it also needs to work for non-integer numbers in the appendix. Alternatively, how can I achieve the look in the picture in some different way?

This is a current MWE of my status:

\documentclass[BCOR=15mm, DIV=8]{scrbook}

\KOMAoptions{
chapterprefix=false,
numbers=noenddot
}

\usepackage{typearea}
\usepackage[utf8]{inputenc}
\usepackage{kpfonts}
\usepackage[T1]{fontenc}
\usepackage{microtype}
\usepackage{lipsum}

\usepackage{tikz}
\usetikzlibrary{
calc,
positioning}
\tikzset{>=latex}
\usepackage{tikzpagenodes}

\usepackage{etoolbox}
\usepackage{xstring}
\usepackage{calc}

\definecolor{laccentcolor}{HTML}{d3d3d3}

% Macro that determines the per-chapter offsets.
% If I use this definition, the document will not finish building.
% \newcommand*{\chapteroffset}{%
% \IfEndWith{\thechapter}{1}{\textwidth+15mm}{%
% \IfEndWith{\thechapter}{2}{\textwidth+5mm}{%
% \IfEndWith{\thechapter}{3}{\textwidth+6mm}{%
% \textwidth+0mm%
% }}}%
% }

% returning a fixed length from the macro like this works
\newcommand*{\chapteroffset}{\textwidth+5mm}

\renewcommand*{\chapterformat}{%
\begin{tikzpicture}[remember picture, overlay]
\node[anchor=south east, yshift=1.2cm, xshift=\chapteroffset,
inner sep=0, outer sep=0]{%
\fontsize{10cm}{10cm}\selectfont%
\textcolor{laccentcolor}{\thechapter}%
};
% alignment line
\draw[thin] (current page text area.north east)
-- (current page text area.south east);
\end{tikzpicture}%
}

\begin{document}
\chapter{A Fancy Chapter Name to Test the Formatting}
\lipsum[1]

\chapter{A Fancy Chapter Name to Test the Formatting}
\lipsum[1]

\chapter{A Fancy Chapter Name to Test the Formatting}
\lipsum[1]
\end{document}

• I'm short in time, so only a note: The commands of xstring are not expandable. So you cannot use them in a context, where you need the expanded result of the test. So it maybe it would be better to define a \setoffset-command that sets a length \chapteroffset and use that command before you need the value, e.g., before the tikzpicture. Also: \thechapter does not need to result in a string only (but in your example it should). – Schweinebacke Mar 6 at 10:41

You could just store the shifts in an array, which you could use. Since you are loading tikzpagenodes, I would also suggest making use of that package.

\documentclass[BCOR=15mm, DIV=8]{scrbook}

\KOMAoptions{
chapterprefix=false,
numbers=noenddot
}

\usepackage{typearea}
\usepackage[utf8]{inputenc}
\usepackage{kpfonts}
\usepackage[T1]{fontenc}
\usepackage{microtype}
\usepackage{lipsum}

\usepackage{tikz}
\usetikzlibrary{
calc,
positioning}
\tikzset{>=latex}
\usepackage{tikzpagenodes}

\usepackage{etoolbox}
\usepackage{xstring}
\usepackage{calc}

\definecolor{laccentcolor}{HTML}{d3d3d3}

% returning a fixed length from the macro like this works
\newcommand*{\chapteroffset}{\textwidth+5mm}

\def\chaplengths{{11mm,5mm,6mm}}
\renewcommand*{\chapterformat}{%
\begin{tikzpicture}[remember picture]
\coordinate (mychapanchor-\arabic{chapter});
\end{tikzpicture}
\begin{tikzpicture}[remember picture, overlay]
\pgfmathsetmacro{\mylength}{\chaplengths[\arabic{chapter}-1]}
\node[anchor=south east,xshift=\mylength,
inner sep=0, outer sep=0]
at ([yshift=1.2cm]mychapanchor-\arabic{chapter}-| current page text area.east){%
\fontsize{10cm}{10cm}\selectfont%
\textcolor{laccentcolor}{\thechapter}%
};
% alignment line
\draw[thin] (current page text area.north east)
-- (current page text area.south east);
\end{tikzpicture}%
}

\begin{document}
\chapter{A Fancy Chapter Name to Test the Formatting}
\lipsum[1]

\chapter{A Fancy Chapter Name to Test the Formatting}
\lipsum[1]

\chapter{A Fancy Chapter Name to Test the Formatting}
\lipsum[1]
\end{document}


• Thanks, that looks like a workable solution, although I would have to hard code which chapters belong to the appendix. I am not familiar with some of the syntax you used: \coordinate (mychapanchor-\arabic{chapter}); Does this just define a new name for the coordinate per chapter or does the dash imply subtraction? ([yshift=1.2cm]mychapanchor-\arabic{chapter}-| current page text area.east) What does the vertical bar | mean here? Is this some way of specifying x and y from different coordinates that I don't know yet? – toster Mar 6 at 16:00
• @toster I am using the array syntax which is explained on p. 999 of the pgfmanual. That is, I store the lengths in \chaplengths by saying \def\chaplengths{{11mm,5mm,6mm}} (note the double { }) and then access them with \pgfmathsetmacro{\mylength}{\chaplengths[\arabic{chapter}-1]} (the -1 is because the first element has array index 0). – marmot Mar 6 at 16:05
• Thanks, but that wasn't the syntax I was unclear on. Please read my comment again. – toster Mar 6 at 19:43
• @toster Sorry, I indeed didn't read carefully. Yes, this defines new coordinates. Strictly speaking this is not necessary but I find that cleaner. What may, however, be important, is to first set some anchor and then use an overlay picture. (I was actually a bit surprised that it worked so well in your code, but would definitely fix it.) And a very nice discussion on -| and |- can be found at tex.stackexchange.com/a/401429/121799. Sorry again! – marmot Mar 6 at 19:47
• Thanks, I just found this syntax in the pgfmanual. It could have saved me a lot of typing in the past. I used to use \let expressions to do stuff like this. – toster Mar 6 at 19:53

You can use \int_case:nnF from expl3:

\documentclass[BCOR=15mm, DIV=8]{scrbook}

\KOMAoptions{
chapterprefix=false,
numbers=noenddot
}

\usepackage{typearea}
\usepackage[utf8]{inputenc}
\usepackage{kpfonts}
\usepackage[T1]{fontenc}
\usepackage{microtype}
\usepackage{lipsum,showframe}

\usepackage{tikz}
\usetikzlibrary{
calc,
positioning}
\tikzset{>=latex}
\usepackage{tikzpagenodes}

\usepackage{xparse}

\definecolor{laccentcolor}{HTML}{d3d3d3}

% Macro that determines the per-chapter offsets.
\ExplSyntaxOn
\NewExpandableDocumentCommand{\chapteroffset}{}
{
\textwidth+
\int_case:nnF { \int_mod:nn { \value{chapter} } { 10 } }
{
{1}{11mm} % shift for last digit 1
{2}{5mm} % shift for last digit 2
{3}{6mm} % shift for last digit 3
}
{1mm} % shift for all other cases
}
\ExplSyntaxOff

\renewcommand*{\chapterformat}{%
\begin{tikzpicture}[remember picture, overlay]
\node[anchor=south east, yshift=1.2cm, xshift=\chapteroffset,
inner sep=0, outer sep=0]{%
\fontsize{10cm}{10cm}\selectfont%
\textcolor{laccentcolor}{\thechapter}%
};
% alignment line
\draw[thin] (current page text area.north east)
-- (current page text area.south east);
\end{tikzpicture}%
}

\begin{document}
\chapter{A Fancy Chapter Name to Test the Formatting}
\lipsum[1]

\chapter{A Fancy Chapter Name to Test the Formatting}
\lipsum[1]

\chapter{A Fancy Chapter Name to Test the Formatting}
\lipsum[1]
\end{document}


If you want to take care of the appendix add a “variable command”. Perhaps scrbook has a built-in conditional for testing whether it is in the appendix part. If so, it shouldn't be difficult to use it instead of the home-made \ifappendix.

\documentclass[BCOR=15mm, DIV=8]{scrbook}

\KOMAoptions{
chapterprefix=false,
numbers=noenddot
}

\usepackage{typearea}
\usepackage[utf8]{inputenc}
\usepackage{kpfonts}
\usepackage[T1]{fontenc}
\usepackage{microtype}
\usepackage{lipsum,showframe}

\usepackage{tikz}
\usetikzlibrary{
calc,
positioning}
\tikzset{>=latex}
\usepackage{tikzpagenodes}

\usepackage{xparse}

\definecolor{laccentcolor}{HTML}{d3d3d3}

% Macro that determines the per-chapter offsets.
\NewExpandableDocumentCommand{\chapteroffset}{}
{
\textwidth+
\ifappendix\offsetforchapter\else\offsetforappendix\fi
}
\newif\ifappendix
\ExplSyntaxOn
\NewExpandableDocumentCommand{\offsetforchapter}{}
{
\int_case:nnF { \int_mod:nn { \value{chapter} } { 10 } }
{
{1}{11mm}
{2}{5mm}
{3}{6mm}
}
{1mm} % all other cases
}
\NewExpandableDocumentCommand{\offsetforappendix}{}
{
\int_case:nnF { \value{chapter} }
{
{1}{11mm} % offset for A
{2}{5mm}  % offset for B
{3}{6mm}  % offset for C
}
{1mm} % all other cases
}
\ExplSyntaxOff

\renewcommand*{\chapterformat}{%
\begin{tikzpicture}[remember picture, overlay]
\node[anchor=south east, yshift=1.2cm, xshift=\chapteroffset,
inner sep=0, outer sep=0]{%
\fontsize{10cm}{10cm}\selectfont%
\textcolor{laccentcolor}{\thechapter}%
};
% alignment line
\draw[thin] (current page text area.north east)
-- (current page text area.south east);
\end{tikzpicture}%
}

\begin{document}

\chapter{A Fancy Chapter Name to Test the Formatting}
\lipsum[1-2]

\chapter{A Fancy Chapter Name to Test the Formatting}
\lipsum[1-2]

\chapter{A Fancy Chapter Name to Test the Formatting}
\lipsum[1-2]

\appendix\appendixtrue

\chapter{A Fancy Chapter Name to Test the Formatting}
\lipsum[1-2]

\end{document}


Based on marmot and egreg's answers, this is what I ended up using:

\newif\ifappendix

\def\chaplengths{{11mm,6mm,7mm,2.5mm,7mm,5mm,6mm,7mm,6.5mm}}
\def\applengths{{4mm,8.5mm,6mm}}
\renewcommand*{\chapterformat}{%
\begin{tikzpicture}[remember picture]
\coordinate (mychapanchor-\arabic{chapter});
\end{tikzpicture}
\begin{tikzpicture}[remember picture, overlay]
\pgfmathsetmacro{\mylength}{\ifappendix\applengths[\arabic{chapter}-1]\else\chaplengths[\arabic{chapter}-1]\fi}
\node[anchor=south east,xshift=\mylength,
inner sep=0, outer sep=0]
at ([yshift=1.2cm]mychapanchor-\arabic{chapter}-| current page text area.east){%
\fontsize{10cm}{10cm}\selectfont%
\textcolor{laccentcolor}{\thechapter}%
};
% alignment line
\draw[thin] (current page text area.north east)
-- (current page text area.south east);
\end{tikzpicture}%
}


Full MWE:

\documentclass[BCOR=15mm, DIV=8]{scrbook}

\KOMAoptions{
chapterprefix=false,
numbers=noenddot
}

\usepackage{typearea}
\usepackage[utf8]{inputenc}
\usepackage{kpfonts}
\usepackage[T1]{fontenc}
\usepackage{microtype}
\usepackage{lipsum}

\usepackage{tikz}
\usetikzlibrary{
calc,
positioning}
\tikzset{>=latex}
\usepackage{tikzpagenodes}

\usepackage{etoolbox}
\usepackage{xstring}
\usepackage{calc}

\definecolor{laccentcolor}{HTML}{d3d3d3}

\newif\ifappendix

\def\chaplengths{{11mm,6mm,7mm,2.5mm,7mm,5mm,6mm,7mm,6.5mm}}
\def\applengths{{4mm,8.5mm,6mm}}
\renewcommand*{\chapterformat}{%
\begin{tikzpicture}[remember picture]
\coordinate (mychapanchor-\arabic{chapter});
\end{tikzpicture}
\begin{tikzpicture}[remember picture, overlay]
\pgfmathsetmacro{\mylength}{\ifappendix\applengths[\arabic{chapter}-1]\else\chaplengths[\arabic{chapter}-1]\fi}
\node[anchor=south east,xshift=\mylength,
inner sep=0, outer sep=0]
at ([yshift=1.2cm]mychapanchor-\arabic{chapter}-| current page text area.east){%
\fontsize{10cm}{10cm}\selectfont%
\textcolor{laccentcolor}{\thechapter}%
};
% alignment line
\draw[thin] (current page text area.north east)
-- (current page text area.south east);
\end{tikzpicture}%
}

\begin{document}
% 1
\chapter{A Fancy Chapter Name to Test the Formatting}
\lipsum[1]

% 2
\chapter{A Fancy Chapter Name to Test the Formatting}
\lipsum[1]

% 3
\chapter{A Fancy Chapter Name to Test the Formatting}
\lipsum[1]

% 4
\chapter{A Fancy Chapter Name to Test the Formatting}
\lipsum[1]

% 5
\chapter{A Fancy Chapter Name to Test the Formatting}
\lipsum[1]

% 6
\chapter{A Fancy Chapter Name to Test the Formatting}
\lipsum[1]

% 7
\chapter{A Fancy Chapter Name to Test the Formatting}
\lipsum[1]

% 8
\chapter{A Fancy Chapter Name to Test the Formatting}
\lipsum[1]

% 9
\chapter{A Fancy Chapter Name to Test the Formatting}
\lipsum[1]

\appendix\appendixtrue

% A
\chapter{A Fancy Chapter Name to Test the Formatting}
\lipsum[1]
% B
\chapter{A Fancy Chapter Name to Test the Formatting}
\lipsum[1]
% C
\chapter{A Fancy Chapter Name to Test the Formatting}
\lipsum[1]
\end{document}