# pgfdeclareshape fillable background path with invisible parts

I want to make a new shape from rectangle, which has only its top and bottom line drawn, but which can be filled. The answer, thank's to Andrew Stacy and percusse look by now as follows:

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\documentclass[twoside,reqno,12pt]{amsart}
\usepackage{a4wide} %% uncomment if a4wide is not installed
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% T i k Z
%%   -- packages
%%   -- macros & shapes
\usepackage{tikz}
\usetikzlibrary{arrows,backgrounds}
\usetikzlibrary{decorations.pathreplacing}
\usetikzlibrary{decorations.markings}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% new shape : iso
%%
\makeatletter
\newif\ifpullback
\pgfkeys{/tikz/pullback/.is if=pullback}
\pgfkeys{/tikz/pullback=false}
\pgfdeclareshape{iso}{%
%
\inheritsavedanchors[from=rectangle]
\inheritanchorborder[from=rectangle]
\inheritanchor[from=rectangle]{north}
\inheritanchor[from=rectangle]{north west}
\inheritanchor[from=rectangle]{north east}
\inheritanchor[from=rectangle]{center}
\inheritanchor[from=rectangle]{west}
\inheritanchor[from=rectangle]{east}
\inheritanchor[from=rectangle]{mid}
\inheritanchor[from=rectangle]{mid west}
\inheritanchor[from=rectangle]{mid east}
\inheritanchor[from=rectangle]{base}
\inheritanchor[from=rectangle]{base west}
\inheritanchor[from=rectangle]{base east}
\inheritanchor[from=rectangle]{south}
\inheritanchor[from=rectangle]{south west}
\inheritanchor[from=rectangle]{south east}
%
\savedanchor\centerpoint
{
\pgf@x=0pt
\pgf@y=0pt
}
\anchor{text}{%
\pgf@x=0pt
\pgf@y=0pt
}
%
\backgroundpath{%
\northeast \pgf@xa=\pgf@x \pgf@ya=\pgf@y
\southwest \pgf@xb=\pgf@x \pgf@yb=\pgf@y
\begingroup
\tikz@mode
\iftikz@mode@draw
% -- draw top and bottom line
\pgfpathmoveto\northeast
\pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@ya}}
\pgfpathmoveto\southwest
\pgfpathlineto{\pgfqpoint{\pgf@xa}{\pgf@yb}}
\pgfusepath{stroke}
\fi
\iftikz@mode@fill
% -- fill rectangle if demanded
\pgfsetlinewidth{\pgflinewidth}
\pgfpathrectanglecorners{\pgfqpoint{\pgf@xb}{\pgf@yb}}{\pgfqpoint{\pgf@xa}{\pgf@ya}}
\pgfusepath{fill}
\fi
\ifpullback
% -- if option pullback is given draw hook
\northeast \pgf@xa=\pgf@x \pgf@ya=\pgf@y
\southwest \pgf@xb=\pgf@x \pgf@yb=\pgf@y
\pgf@xc=\pgf@xb
\pgf@yc=\pgf@ya
\pgfpathmoveto{\pgfqpoint{\pgf@xc}{\pgf@ya}}
\pgfpathlineto{\pgfqpoint{\pgf@xc}{\pgf@yc}}
\pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@yc}}
\pgfusepath{stroke}
\fi
\endgroup
}
}
\makeatother
\begin{document}

\begin{tikzpicture}
\draw (0,-2) grid (6,3);
\node[fill=blue!20,line width=2pt,iso,draw,minimum width=2.5cm,inner ysep=0pt] at (2,2){$=$};
\node[fill=green!20,pullback,line width=1.25pt,iso,draw,minimum width=2.5cm,inner ysep=0pt] at (2,1){$=$};
\end{tikzpicture}
\end{document}


This solution also takes care of the fact that the rectangle used to fill the box overrides part of the top and bottom lines, halving their width. Hence before drawing the filler rectangle, the northeast and southwest y-coordinates are altered by half \pgflinewidth. On option pullback is added which draws a small hock in the top left corner. [This shape is meant to depict a iso-2-cell in 2-tangles for 2-categories].

-
Short answer is that you can't. A path has to have constant width and so you can't have some bits invisible and some visible. So you need two paths, as percusse's answer gives. (Longer explanation at the question I linked to under percusse's answer) –  Loop Space Mar 31 '12 at 20:39
It's best to leave the question as the question, otherwise it's hard for others to see what the problem was and so to benefit from the answer. If you feel that the code you actually end up with is interestingly different to the answer you were given the it is quite alright to post your own answer - just make sure to attribute it correctly, and ettiquete says you shouldn't accept your own answer if it was derived from another's. –  Loop Space Apr 1 '12 at 21:23
@AndrewStacey I agree with both of you and glad that a simple swap was adequate. Indeed you can show off your end solution with an image that you can upload to your answer (via using the image button on the toolbar). –  percusse Apr 1 '12 at 21:54

The following does the job (thanks to Andrew Stacey's nice correction).

\documentclass{article}
\usepackage{tikz}

\makeatletter
\pgfdeclareshape{iso}{%
%
\inheritsavedanchors[from=rectangle]
\inheritanchorborder[from=rectangle]
\inheritanchor[from=rectangle]{north}
\inheritanchor[from=rectangle]{north west}
\inheritanchor[from=rectangle]{north east}
\inheritanchor[from=rectangle]{center}
\inheritanchor[from=rectangle]{west}
\inheritanchor[from=rectangle]{east}
\inheritanchor[from=rectangle]{mid}
\inheritanchor[from=rectangle]{mid west}
\inheritanchor[from=rectangle]{mid east}
\inheritanchor[from=rectangle]{base}
\inheritanchor[from=rectangle]{base west}
\inheritanchor[from=rectangle]{base east}
\inheritanchor[from=rectangle]{south}
\inheritanchor[from=rectangle]{south west}
\inheritanchor[from=rectangle]{south east}
%
\savedanchor\centerpoint
{
\pgf@x=0pt
\pgf@y=0pt
}
\anchor{text}{%
\pgf@process{\centerpoint}
}
%
\backgroundpath{%
\northeast \pgf@xa=\pgf@x \pgf@ya=\pgf@y
\southwest \pgf@xb=\pgf@x \pgf@yb=\pgf@y
\begingroup
\tikz@mode

\iftikz@mode@fill
\pgfpathrectanglecorners{\northeast}{\southwest}
\pgfusepath{fill}
\fi
\iftikz@mode@draw

\pgfpathmoveto\northeast
\pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@ya}}
\pgfpathmoveto\southwest
\pgfpathlineto{\pgfqpoint{\pgf@xa}{\pgf@yb}}
\pgfusepath{stroke}
\fi
\endgroup
}
}
\makeatother
\begin{document}
\begin{tikzpicture}
\node[iso,draw,fill=yellow] (a) at (0,0) {slight yellow};
\end{tikzpicture}
\end{document}


-
You need to test \iftikz@mode@fill. See this question for an example: tex.stackexchange.com/q/45567/86 –  Loop Space Mar 31 '12 at 20:35
@AndrewStacey I took a slightly different path but I am not sure if it is indeed robust. –  percusse Mar 31 '12 at 20:36
You're restricting your options that way. You can't use color and you can't turn off the drawn lines. Okay, so it's hard to imagine wanting to do those with this example, but it's good discipline to not impose unnecessary restrictions. –  Loop Space Mar 31 '12 at 20:48
@AndrewStacey That's indeed my motivation since if you don't need the lines you don't use the iso key anyway. –  percusse Mar 31 '12 at 20:50
True. But you could do an every node/.style={iso} if you only had a few that didn't need the lines, then not draw those lines on the few rather than changing the shapes. –  Loop Space Mar 31 '12 at 20:52