8

In this answer and this answer, an nice method of clipping TikZ stuff against the contours of some characters have been proposed: use the character for tikzfadingfrompicture and then use that fading to clip away stuff that's outside of the contour. Overall, this works great but it seems that at large magnifications some manual shifts are required to obtain the desired result. Consider the MWE (that was triggered by this question)

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{fadings,positioning}
\usepackage{contour}
\contournumber{32}
\begin{tikzfadingfrompicture}[name=5-0]
\node[transparent!0,scale=15] (5) at (0,0) {5};
\end{tikzfadingfrompicture}
\begin{tikzfadingfrompicture}[name=5-1]
\node[transparent!0,scale=15] (5) at (0,0) {5};
\path (5.south) -- ++ (0,-0.1);
\end{tikzfadingfrompicture}
\begin{document}
\begin{tikzpicture}
   \node[white,scale=15] (5-1) {\contour{blue}{5}};
   \foreach \x in {1,1.2,...,3.4}
   \foreach \y in {0.1,0.4,...,4.5}
   {
       \path[path fading=5-1,fit fading=false] 
       ({\x-2},{\y-2.5}) node {5};
   }
   \node[above=0pt of 5-1]{contour shifted by hand};
\end{tikzpicture}
~
\begin{tikzpicture}
   \node[white,scale=15] (5-0) {\contour{blue}{5}};
   \foreach \x in {1,1.2,...,3.4}
   \foreach \y in {0.1,0.4,...,4.5}
   {
       \path[path fading=5-0,fit fading=false] 
       ({\x-2},{\y-2.5}) node {5};
   }
   \node[above=0pt of 5-0]{contour not shifted};
   \draw[thick,red] ([yshift=-1.9cm]5-0.north) circle (1cm and 3pt)
   ([yshift=-3.1cm]5-0.north) circle (1cm and 3pt)
   ([yshift=-4.15cm,xshift=-0.75cm]5-0.north) circle (0.3cm and 3pt)
   ([yshift=-5.2cm]5-0.north) circle (0.5cm and 3pt);
\end{tikzpicture}
\end{document}

enter image description here

The left contour is what I would call the desired output but it seems to require a manual shift achieved by \path (5.south) -- ++ (0,-0.1); in the corresponding tikzfadingfrompicture. The right contour does not have the manual adjustment, and therefore there are gaps, which are marked in red, as well as overlaps, which are harder to see, and which I did not mark.

Question: Why is that? Am I doing something obviously wrong? And, most importantly, is there a non-manual way to fix this?

Bonus question: Is there a simple way to move the path fading, i.e. to make it work if I place the big 5 at an arbitrary point, not at (0,0)?

1 Answers1

9

It seems contour lifts the node by half the contour line width, specified by \contourlength. In the code of contour this line width is stored in \con@base@length, so by lowering the contour node by half this value the small 5 and the contour 5 should align. Test (I also included one with scale 10 and (un-scaled) contour width 0.7pt):

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{fadings,positioning}
\usepackage{contour}
\contournumber{32}
\begin{tikzfadingfrompicture}[name=5-0]
  \node[transparent!0,scale=15] (5) at (0,0) {5};
\end{tikzfadingfrompicture}
\begin{tikzfadingfrompicture}[name=5-10]
  \node[transparent!0,scale=10] (5) at (0,0) {5};
\end{tikzfadingfrompicture}
%%%
\begin{document}
\begin{tikzpicture}
  \makeatletter
  \node[white,inner sep=1pt,scale=15,yshift=-0.5*\con@base@length] (5-0c) {\contour{blue}{5}};
  \makeatother
  \foreach \x in {1,1.2,...,3.4}
  \foreach \y in {0.1,0.4,...,4.5}
  {
    \path[path fading=5-0,fit fading=false] 
    ({\x-2},{\y-2.5}) node {5};
  }
\end{tikzpicture}
\contourlength{0.7pt}
\begin{tikzpicture}
  \makeatletter
  \node[white,inner sep=1pt,scale=10,yshift=-0.5*\con@base@length] (5-10c) {\contour{blue}{5}};
  \makeatother
  \foreach \x in {1,1.2,...,3.4}
  \foreach \y in {0.1,0.4,...,4.5}
  {
    \path[path fading=5-10,fit fading=false] 
    ({\x-2},{\y-2.5}) node {5};
  }
\end{tikzpicture}
\end{document}

enter image description here

The reason the node is lifted by half the contour line is how contour sets the box around the text. From

\fboxsep=0pt
\fbox{\Huge A}\fbox{\contour{red}{\color{white}\Huge A}}

enter image description here

one can see that it is lowered below the text but not increased in height (or width). When putting this in a node, it is aligned in the center, and the contour text will be lifted by half the line width.

\begin{tikzpicture}[node distance=0pt]
  \node[inner sep=0pt] (A) {\fbox{\Huge A}};
  \node[inner sep=0pt,right=of A] (Acol) {\fbox{\contour{red}{\color{white}\Huge A}}};  
  \fill[green] (A) circle (1pt);
  \fill[green] (Acol) circle (1pt);
\end{tikzpicture}

enter image description here

StefanH
  • 13,823
  • 2
    @marmot I have added my interpretation of why it is lifted half line width. – StefanH Jul 08 '18 at 13:53
  • 1
    Got it. Thanks! Great research!!! (To me it seems also a bit odd that the bounding box is increased in this asymmetric way... ) –  Jul 08 '18 at 13:57
  • 2
    Yes, I agree. I can understand that the depth of the text should increase with the line width. But that does not explain why the height is not increased. – StefanH Jul 08 '18 at 14:30