# Is it possible to clear tikz/pgf options?

According to the pgfmanual, setting options on a clipping path is Not Allowed, so

\clip[fill=red] (0,0) circle (1);


doesn't work. That's all very well, and the above is certainly avoidable.

However, what also doesn't work is when these options are set implicitly, say by providing an every path/.style={fill=red} on the encompassing scope.

Is there some way to have my path and clip it? That is, is there some way to clear the current global settings on an individual path?

Here's an example of the sort of thing I'd like to be able to do (but can't):

\documentclass{article}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}[every path/.style={fill=red}]
\clip (0,0) -- (1,0) -- (1,1) -- (0,0);
\draw (0,0) rectangle (1,1);
\end{tikzpicture}
\end{document}


(I should emphasise that this is a minimal example: in the actual case, I have lots of paths and lots of different layers and scopes, and would really like to be able to specify the default path style on the main tikzpicture environment. Even doing this:

\documentclass{article}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\clip (0,0) -- (1,0) -- (1,1) -- (0,0);
\begin{scope}[every path/.style={fill=red}]
\draw (0,0) rectangle (1,1);
\end{scope}
\end{tikzpicture}
\end{document}


would, in the resulting Real World implementation, be irritating.)

In case it helps, I'm using TeXLive 2010 but with pgf dated 2010-07-25.

• Funny quote from the manual: "You cannot specify certain graphic options for the command used for clipping.... The reasons for this have to do with the internals of the pdf specification. You do not want to know the details." – Matthew Leingang Nov 4 '10 at 10:16
• @Matthew Leingang: Fake quote inspired by real ones: "If you don't know what the pdf specification is, you are blessed". – Ryan Reich Nov 25 '10 at 6:57
• See also Tikz style conflicting with clip command... – Paul Gaborit Dec 28 '12 at 8:12

This seems to work. Is it preferable?

\begin{tikzpicture}[every path/.style={fill=red}]
{
\tikzset{every path/.style={}}
\clip (0,0) -- (1,0) -- (1,1) -- (0,0);
}
\draw (0,0) rectangle (1,1);
\end{tikzpicture}


Edited 2012-12-27 by Andrew Stacey An issue with the above is how clip interacts with setting the bounding box. When a clip is in force, the clipping path should set the bounding box and all clipped paths should not be taken into account when computing the bounding box. Unfortunately, while a clip lasts until the end of a scope, the method by which subsequent paths are ignored (for bounding box computations) only lasts to the end of the current group. I (Andrew Stacey) would actually class this as a TikZ bug: since the clip lasts to the end of the scope the restriction on the bounding box computation should equally last to the end of the scope. There are various ways to fix this:

1. Since it is usual to restrict a clip to within a scope, put every path/.append style={overlay} on the relevant scope:

\begin{tikzpicture}[every path/.style={fill=red}]
\begin{scope}[every path/.append style={overlay}]
{
\tikzset{every path/.style={}}
\clip (0,0) -- (1,0) -- (1,1) -- (0,0);
}
\draw (-1,-1) rectangle (2,2);
\end{scope}
\end{tikzpicture}


The overlay is removed from the clip path as its options are cleared, but it is retained on all other paths in the scope.

2. For a little more intuitive control, the overlay key can be augmented to take true or false (though due to implementation the value of true/false needs inverting). Then:

\documentclass{article}
\usepackage{tikz}

\def\invertTFtrue{false}
\def\invertTFfalse{true}
\tikzoption{overlay}[true]{\csname pgf@relevantforpicturesize\csname
invertTF#1\endcsname\endcsname}

\begin{document}

\fbox{%
\begin{tikzpicture}[every path/.style={fill=red}]
\begin{scope}[overlay]
{
\tikzset{every path/.style={}}
\clip[overlay=false] (0,0) -- (1,0) -- (1,1) -- (0,0);
}
\draw (-1,-1) rectangle (2,2);
\end{scope}
\end{tikzpicture}}
\end{document}

3. Lastly, the overlay/clip mechanism can be fixed so that it works with scopes rather than groups. To do this properly and elegantly would require fixing the underlying code a little, the following uses the available hooks to achieve the same end.

\documentclass{article}
\usepackage{tikz}

\makeatletter

\def\invertTFtrue{false}
\def\invertTFfalse{true}

\tikzset{
fix clips to scope/.style={%
every scope/.append style={%
execute at end scope={%
\expandafter\global\csname               pgf@relevantforpicturesize\savescopeoverlay\endcsname
},
execute at begin scope={%
\edef\savescopeoverlay{\ifpgf@relevantforpicturesize true\else                   false\fi}%
}
},
globalise overlays,
clip/.append code={\aftergroup\globaloverlay}
},
globalise overlays/.code={%
\tikzoption{overlay}[true]{\expandafter\global\csname       pgf@relevantforpicturesize\csname invertTF#1\endcsname\endcsname}
}
}

\def\globaloverlay{\global\pgf@relevantforpicturesizefalse}
\makeatletter

\begin{document}

\fbox{%
\begin{tikzpicture}[fix clips to scope,every path/.style={fill=red}]
\begin{scope}
{
\tikzset{every path/.style={}}
\clip (0,0) -- (1,0) -- (1,1) -- (0,0);
}
\draw (-1,-1) rectangle (2,2);
\end{scope}
\draw (-1,1) rectangle (2,2);
\end{tikzpicture}}
\end{document}

• Yes, that is definitely preferable. It seems to be exploiting a distinction between TeX scopes and TikZ scopes. So \tikzset applies to the current TeX scope but the path clip applies to the current TikZ scope. Neat! – Loop Space Nov 4 '10 at 11:49
• I can confirm that it is correct that setting keys by means of \tikzset (and \pgfkeys in general) is always limited to the current TeX group whereas clip paths live throughout the TikZ scope (it is communicated to the backend driver). – Christian Feuersänger Nov 1 '11 at 14:44
• Matthew, it was pointed out that this solution breaks bounding box computations. I edited a fix in to your answer. Hope this is okay! – Loop Space Dec 27 '12 at 17:46
• @AndrewStacey: I just noticed this. Thanks for fixing. – Matthew Leingang May 9 '13 at 11:54