How to control the fading size in TikZ?

I am trying to create a fading using tikzfadingfrompicture, but I cannot understand how TikZ computes the size of the fading. I assumed that TikZ calculates the bounding box of the image to fade, and then stretches the fading-picture to match its bounding box with the bounding box of the image, but the following code snippet proves I am wrong.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{patterns,fadings}

\begin{document}

\begin{tikzfadingfrompicture}[name=fade frame]
\draw[transparent!0,step=0.2cm] (-1,-1) grid (1,1);
\end{tikzfadingfrompicture}

\begin{tikzpicture}
\fill [black!20] (-2,-2) rectangle (7,7);
\pattern [pattern=checkerboard, pattern color=black!30] (-2,-2)
rectangle (7,7);
\draw[step=0.5cm,very thin] (-2,-2) grid (7,7);
\fill [path fading=fade frame,red] (-2,-2) rectangle (7,7);
\end{tikzpicture}

\end{document}


The picture I get has 9 squares, and not 10 as I would expect (because the original grid in the fading is 2cm wide and has a step=0.2cm). Am I doing something wrong? How can I have TikZ use the whole fading-picture?

-
Sorry for my ignorance but why would you expect 10? BTW, can you add \usetikzlibrary{fadings},\usetikzlibrary{patterns} to your code as well as the \begin{document},end{document} etc. to make it a minimal working example. It makes it easier to copy and paste. –  percusse Jun 1 '11 at 9:45
@percusse: I expect 10 boxes because I draw a 2cm wide grid with step=0.2cm. Here is the complete code: –  Marco Lombardi Jun 1 '11 at 9:50
@Marco : Ouch. You get n division not n-1 of course :) So, I have added fit fading = false option in the last fill command and saw that it is indeed creating a 10x10 block. But stretching this guide seems to be your problem. –  percusse Jun 1 '11 at 10:16
@Marco: In fact if you just use \draw[transparent!0,step=0.2cm] (0,0) grid (1,1); gives exactly what you wanted, but obviously, does not qualify as an answer. What I am puzzled the most is that the pattern seems to agree in the center of the figure but not towards the corners. –  percusse Jun 1 '11 at 16:22
@percusse: Thank you again for pointing this. I start to think that either there is a bug in pgf/TikZ... If this is not solved perhaps I should contact the developers. –  Marco Lombardi Jun 1 '11 at 22:11

1 Answer

The following is 50% experiment, 50% trying to read the TikZ code, and 100% guesswork.

It appears that when TikZ/PGF uses a path as a fading then it doesn't use the whole path. Indeed, this is pretty clear from the following comment in the file pgfcoretransparency.code.tex:

% This command works a bit like \pgfshadepath. "Works a bit like"
% means the following: The masks's original size should
% completely cover the area between (0,0) and (100bp,100bp). The
% mask is then rescaled so that it completely covers the path.


The key part is that bit about the "masks's [sic] original size". This indicates that when specifying a fading from a picture (or path) then the actual mask used is whatever lies in a certain box, not the entire picture. (One can dispute whether or not this is the Right Thing to Do, but this isn't the place for that.)

However the rectangle suggested in the above comment does not appear to be the right one. (This is where the experiments come in.) What appears to happen is that the segment used is that from the centre of the picture with size 50bp. That is, find the centre of the picture and plonk a square of side length 50bp so that its centre is at the centre of the picture.

To see that this is the case, we can consider the example given in the aforementioned file:

 \pgfdeclarefading{fade right}
{\tikz[left color=transparent!0,right color=transparent!100]
(0,0) rectangle (100bp,100bp);}


This would appear to define a rectangular shading from full colour at the left to fully transparent at the right. The following code shows that this isn't what happens. Indeed, to get that result we have to cut the size down to 50bp:

\documentclass{standalone}
%\url{http://tex.stackexchange.com/q/19596/86}
\usepackage{tikz}
\usetikzlibrary{patterns,fadings}

\begin{document}

\pgfdeclarefading{test fading b}
{\tikz
\fill[left color=transparent!0,right color=transparent!100] (0,0) rectangle (50bp,50bp);}

\pgfdeclarefading{test fading a}
{\tikz
\fill[left color=transparent!0,right color=transparent!100] (0,0) rectangle (100bp,100bp);}

\begin{tikzpicture}[scale=2]
\fill[gray!50] (-.5,-.5) rectangle (3.5,1.5);
\filldraw[path fading=test fading a,fill=purple] (0,0) rectangle (1,1);
\filldraw[path fading=test fading b,fill=purple] (2,0) rectangle (3,1);
\end{tikzpicture}
\end{document}


Further experimenting does show that the section of the fading used is the centre of the given picture.

Now we can see what goes wrong with your fading. If we draw the actual picture (with the colours changed so that we can see them) and superimpose a square of size 50bp then we can see why the fading produced is only 9 squares.

\documentclass{standalone}
%\url{http://tex.stackexchange.com/q/19596/86}
\usepackage{tikz}
\usetikzlibrary{patterns,fadings}

\begin{document}

\begin{tikzpicture}[scale=4]
\draw[black,step=0.2cm] (-1,-1) grid (1,1);
\draw[red] (-25bp,-25bp) rectangle (25bp,25bp);
\end{tikzpicture}
\end{document}


(The scales in all these are just to get decent sized images; they make no actual difference.)

This corresponds with what we get when we compile your code:

So the solution is to draw the original fading in a box of side length 50bp. This then gives the desired outcome.

\documentclass{standalone}
%\url{http://tex.stackexchange.com/q/19596/86}
\usepackage{tikz}
\usetikzlibrary{patterns,fadings}

\begin{document}

\begin{tikzfadingfrompicture}[name=fade frame]
\draw[transparent!0,step=5bp] (0,0) grid (50bp,50bp);
\end{tikzfadingfrompicture}

\begin{tikzpicture}
\fill [black!20] (-2,-2) rectangle (7,7);
\pattern [pattern=checkerboard, pattern color=black!30] (-2,-2)
rectangle (7,7);
\draw[step=0.5cm,very thin] (-2,-2) grid (7,7);
\fill [path fading=fade frame,red] (-2,-2) rectangle (7,7);
\end{tikzpicture}
\end{document}


(The more I think about this, the more I can see that there is a sort of logic to having it work this way. But reasonable or not, this appears to be undocumented and that is certainly less than ideal!)

-
Well, I will take some time for me to digest this. But nevertheless, thanks a lot for relieving some of the pain :) –  percusse Sep 5 '11 at 12:46