# Bug in TikZ? Line width on layers

I found a curios behavior in TikZ. If I set the line width globaly or for the current scope it wont affect the line with inside a {pgfonlayer} but the arrow tips are changed:

Did I found a bug and does anyone know a solution or at least a workaround?

Code

\documentclass{minimal}

\usepackage{tikz}
\pgfdeclarelayer{background}
\pgfsetlayers{background,main}

\begin{document}
\begin{tikzpicture}[line width=5pt]
\draw (0,0) -- (5,0);
\draw [<->] (0,1) -- (5,1);
\begin{pgfonlayer}{background}
\draw (0,2) -- (5,2) node [right] {on BG};
\draw [<->] (0,3) -- (5,3) node [right] {on BG};
\end{pgfonlayer}
\end{tikzpicture}
\end{document}


## Update

As Christian Feuersäger said, it could be a feature that a new layer sets a fully new picture with the default settings. But in this case all settings should be reset. And in my opinion the every picture style should be evaluated anyway.

Here’s an extended example showing the inconsequent behavior with every picture (color is taken only for nodes of background layer, line width is completely ignored and arrow tips are changed even according to the line width setting).
It shows also my workaround, since I’m using a shortcut for the {pgfonlayer} environment it was easy to add a scope which uses every picture. Unfortunately this {scope}doesn’t respect settings given directly to the {tikzpicture}. And it seems to be incompatible with Caramdir’s \makeatletter\tikz@options\makeatother workaround …

\documentclass{minimal}

\usepackage{tikz}
\pgfdeclarelayer{background}
\pgfsetlayers{background,main}
\tikzset{every picture/.style={line width=5pt,blue,>=stealth}}

\newcommand{\bglayer}[1]{%
\begin{pgfonlayer}{background}
\begin{scope}[every picture]
#1
\end{scope}
\end{pgfonlayer}
}

\begin{document}
\begin{tikzpicture}[green]
\draw (0,0) -- (5,0);
\draw [<->] (0,1) -- (5,1);
\bglayer{%
\draw (0,2) -- (5,2) node [right] {on BG};
\draw [<->] (0,3) -- (5,3) node [right] {on BG};
}
\end{tikzpicture}
\end{document}


-
I come across this problem a lot. I'd be very interested to see if it's something we're doing wrong or a bug. –  qubyte Nov 3 '11 at 23:45
Just a little comment about the arrows. This shows that arrows are set at "definition-time" in that the shape and size of the arrows are set before the line is stuck into the layer box. Whereas the line width is set at render-time. –  Loop Space Nov 5 '11 at 18:56

As noted in a comment, I believe that the PGF responsible will see your request as a feature request (not a bug report). As such, it might take longer for results. But perhaps the PGF responsible will see that it is quite unexpected that options set for the complete picture are not part of the layer, he may want to implement a fix for that particular part, I do not know. Many words just to state: I would like a better solution as well. But be prepared to wait (perhaps very long).

In the meantime, it might help to understand how the given layering architecture works in order to avoid such problems.

Here is what I understand of it. It consists of the interaction between

1. layers
2. option changes (especially styles)
3. graphics settings

Usually, you can change options as you want and at any time. If you change styles, the styles will be evaluated on usage (for example every node will be evaluated during \node). But options which affect the graphics state (like color, linewidth and similar ones) are different: they are applied by scopes (at least I think so) and by \paths (including \draw, of course).

Whenever you switch the layer, pgf starts to collect low level drawing instructions into a different box. All low level drawing instructions which have been collected in a different layer will NOT be copied into the new layer.

This is pretty clear. But since "low level drawing instruction" includes things like \pgfsetlinewidth as well as color assignments, such settings are not copied to the activated layer as well.

After switching to the new layer, PGF will continue its normal processing. In particular, it will continue to evaluate styles, and these styles still have the same value as they had before switching layers.

I suppose this is also not new for you. But it means that you can (and perhaps should) define (custom) styles to share options between layers. Your approach with the every picture style actually uses the approach, but it can be applied in general.

For example,

\begin{tikzpicture}
\tikzset{my style/.style={red,line width=10pt}}
\begin{scope}[my style]
...
\end{scope}

\pgfonlayer{...}
\begin{scope}[my style]
...
\end{scope}
\endpgfonlayer}
\end{tikzpicture}


will do the job. It is not as simple as one would like (or expect), I agree. But this is how it has been designed until now; everything else will have to wait (until someone implements an improved version).

In other words: your approach with the every picture is correct and perhaps the only way to do it right now.

Concerning the "reset": as explained, a layer does not introduce a completely new picture. It inherits all current styles and all current options (except for those graphics state options which have already been written to its layer). Thus, "resetting" anything is not an option.

-
Thanks for this explanation! “Concerning the "reset": …” Ok but I thought the size of an arrow tip is depending on the line width so if the line width is set by {pgfonlayer} the arrow tips should be set to the normal size as well, thats what I meant as an inconsequent resetting chiefly. –  Tobi Nov 4 '11 at 15:45
@Tobi I see your point. –  Christian Feuersänger Nov 5 '11 at 1:24

This seems to be bug in pgf: path styles like \pgfsetlinewidth seem to be forgotten when the layers are set. I have no idea why this happens. Here is a minimal example directly in pgf:

\documentclass{article}

\usepackage{pgf}
\pgfdeclarelayer{background}
\pgfsetlayers{background,main}

\begin{document}
\begin{pgfpicture}
\pgfsetlinewidth{5pt}
\pgfpathmoveto{\pgfpointorigin}
\pgfpathlineto{\pgfpoint{5cm}{0cm}}
\pgfusepath{draw}

\begin{pgfonlayer}{background}
\pgfpathmoveto{\pgfpoint{0cm}{1cm}}
\pgfpathlineto{\pgfpoint{5cm}{1cm}}
\pgfusepath{draw}
\end{pgfonlayer}
\end{pgfpicture}
\end{document}


Using TikZ, you can add \makeatletter\tikz@options\makeatother after \begin{pgfonlayer}{background}. This should get you the options set in the last scope (or tikzpicture), but it won't work correctly if you have nested scopes (i.e. only the options from the innermost scope are used).

-
I reported the bug: sourceforge.net/tracker/… –  Caramdir Nov 4 '11 at 0:06
Technically, the observed problem arises because each layer collects the complete graphics state on its own. I am honestly unsure of whether this is a bug or a feature request. It should work if you replicate the changes of the graphics state to each layer (for example, by replicating \begin{scope}[<options>] for each layer). Anyway, introducing a completely hierarchy graphics state inheritance (which appears to be your expectation) might be way to involved. –  Christian Feuersänger Nov 4 '11 at 8:35
Thanks for reporting the bug! –  Tobi Nov 4 '11 at 9:32
@ChristianFeuersänger: But if the actual behavior is a feature all settings should be reset (please see the update to my question). –  Tobi Nov 4 '11 at 9:46
There is a slight misunderstanding: I meant it is either a bug report or a feature request. If the pgf responsible considers this to be a bug, he may want to fix it. It he considers it to be a feature request, he may reject or postpone it. I am not responsible for this feature, but I would consider it to be a feature request. –  Christian Feuersänger Nov 4 '11 at 13:23