% Copyright 2014 by Jan Bredereke
%
% This file may be distributed and/or modified
%
% 1. under the LaTeX Project Public License and/or
% 2. under the GNU Public License.
%
% See the file doc/generic/pgf/licenses/LICENSE for more details.

% Version: 8 July 2014


% templates for usage, with all options:
%
% \node [nmosfet,%
% 	transistor S label=S,%
% 	transistor D label=D,%
% 	transistor G label=G,%
% 	transistor B label=B,%
% 	transistor label color=black,%
% 	transistor G center,%
% 	transistor G top,% not evaluated if transistor G center
% 	transistor B invisible,%
% 	transistor B not connected to S,%
% 	draw=red,%
% 	fill=red,% for the arrow only
%   ] (nf) at (0,0) {$T_1$};
%
% \node [pmosfet,%
% 	transistor S label=S,%
% 	transistor D label=D,%
% 	transistor G label=G,%
% 	transistor B label=B,%
% 	transistor G center,%
% 	transistor G bottom,% not evaluated if transistor G center
% 	transistor B invisible,%
% 	transistor B not connected to S,%
% 	draw=red,%
% 	fill=red,% for the arrow only
%   ] (pf) at (0,0) {$T_2$};


% Define variant switches and default text labels inside transistor
\pgfkeys{/pgf/.cd,
	transistor S label/.initial=,% (empty)
	transistor D label/.initial=,% (empty)
	transistor G label/.initial=,% (empty)
	transistor B label/.initial=,% (empty)
	transistor label color/.initial=black,%
	transistor G center/.is if=pgftransistorGcenter,%
	transistor G top/.is if=pgftransistorGtop,%
	transistor G bottom/.is if=pgftransistorGbottom,%
	transistor B invisible/.is if=pgftransistorBinvisible,%
	transistor B not connected to S/.is if=pgftransistorBnotconnectedtoS,%
}

% Define default style for these nodes
\tikzset{transistor/port labels/.style={font=\sffamily\small}}
\tikzset{every nmosfet node/.style={%
	draw,%
	minimum width=0.8cm,%
	minimum height=1.4cm,%
% 	thick,%
	inner sep=1mm,%
	outer sep=0pt,%
% 	cap=round,%
	add font=\sffamily},%
}
\tikzset{every pmosfet node/.style={%
	draw,%
	minimum width=0.8cm,%
	minimum height=1.4cm,%
% 	thick,%
	inner sep=1mm,%
	outer sep=0pt,%
% 	cap=round,%
	add font=\sffamily},%
}

% Key to add font macros to the current font
\tikzset{add font/.code={%
	\expandafter\def\expandafter\tikz@textfont%
	\expandafter{\tikz@textfont#1}
	}
}

\newif\ifpgftransistorBinvisible
\newif\ifpgftransistorBnotconnectedtoS
\newif\ifpgftransistorGcenter
\newif\ifpgftransistorGtop
\newif\ifpgftransistorGbottom

% NMOSFET transistor shape
%
\pgfdeclareshape{nmosfet}{
  % The 'minimum width' and 'minimum height' keys, not the content, determine
  % the size
  \savedanchor\D{%
    \pgfmathsetlength\pgf@x{\pgfshapeminwidth}%
    \pgfmathsetlength\pgf@y{\pgfshapeminheight}%
    \pgf@x=0.5\pgf@x
    \pgf@y=0.5\pgf@y
  }
  \savedanchor\G{%
    % This is redundant, but we can't call \D here:
    \pgfmathsetlength\pgf@x{\pgfshapeminwidth}%
    \pgfmathsetlength\pgf@y{\pgfshapeminheight}%
    \pgf@x=0.5\pgf@x
    \pgf@y=0.5\pgf@y
    %
    \pgf@x=-1\pgf@x%
    \ifpgftransistorGcenter
      \pgf@y=0\pgf@y%
    \else
      \ifpgftransistorGtop
	\pgf@y=.45\pgf@y%
      \else
	\pgf@y=-.45\pgf@y%
      \fi
    \fi
  }

  % Inherit from rectangle
  \inheritanchorborder[from=rectangle]

  % Define same anchors a normal rectangle has
  \anchor{center}{\pgfpointorigin}
  \anchor{north}{\D \pgf@x=0pt}
  \anchor{east}{\D \pgf@y=0pt}
  \anchor{south}{\D \pgf@x=0pt \pgf@y=-\pgf@y}
  \anchor{west}{\D \pgf@x=-\pgf@x \pgf@y=0pt}
  \anchor{north east}{\D}
  \anchor{north west}{\D \pgf@x=-\pgf@x}
  \anchor{south west}{\D \pgf@x=-\pgf@x \pgf@y=-\pgf@y}
  \anchor{south east}{\D \pgf@y=-\pgf@y}
  \anchor{text}{
    % put text label above the transistor:
    \D
    \pgf@x=0\pgf@x%
    \pgf@y=1.3\pgf@y%
    % adjust for the size of the text box:
    \advance\pgf@x by -1.0\wd\pgfnodeparttextbox%
%     \advance\pgf@y by -.5\ht\pgfnodeparttextbox%
    \advance\pgf@y by 1.0\dp\pgfnodeparttextbox%
  }

  % Define anchors for signal ports
  \anchor{G}{%
    \pgf@process{\G}%
  }
  \anchor{S}{
    \pgf@process{\D}%
    \pgf@x=1\pgf@x%
    \pgf@y=-1\pgf@y%
  }
  \anchor{D}{
    \pgf@process{\D}%
    \pgf@x=1\pgf@x%
    \pgf@y=1\pgf@y%
  }
  \anchor{B}{
    \pgf@process{\D}%
    \pgf@x=1\pgf@x%
    \pgf@y=0\pgf@y%
  }

  % Draw the transistor, except the arrow
  \backgroundpath{
    % Dashed line from source to drain
    \D
    \pgf@xa=\pgf@x%
    \pgf@ya=\pgf@y%
    \pgf@x=0\pgf@xa%
    \pgf@y=.6\pgf@ya%
    \pgfpathmoveto{\pgfpoint{\pgf@x}{\pgf@y}}
    \pgf@x=0\pgf@xa%
    \pgf@y=.3\pgf@ya%
    \pgfpathlineto{\pgfpoint{\pgf@x}{\pgf@y}}
    \pgf@x=0\pgf@xa%
    \pgf@y=.15\pgf@ya%
    \pgfpathmoveto{\pgfpoint{\pgf@x}{\pgf@y}}
    \pgf@x=0\pgf@xa%
    \pgf@y=-.15\pgf@ya%
    \pgfpathlineto{\pgfpoint{\pgf@x}{\pgf@y}}
    \pgf@x=0\pgf@xa%
    \pgf@y=-.3\pgf@ya%
    \pgfpathmoveto{\pgfpoint{\pgf@x}{\pgf@y}}
    \pgf@x=0\pgf@xa%
    \pgf@y=-.6\pgf@ya%
    \pgfpathlineto{\pgfpoint{\pgf@x}{\pgf@y}}
    % Line from drain segment to drain anchor
    \pgf@x=0\pgf@xa%
    \pgf@y=.45\pgf@ya%
    \pgfpathmoveto{\pgfpoint{\pgf@x}{\pgf@y}}
    \pgf@x=1\pgf@xa%
    \pgf@y=.45\pgf@ya%
    \pgfpathlineto{\pgfpoint{\pgf@x}{\pgf@y}}
    \pgf@x=1\pgf@xa%
    \pgf@y=.45\pgf@ya%
    \pgfpathmoveto{\pgfpoint{\pgf@x}{\pgf@y}}
    \pgf@x=1\pgf@xa%
    \pgf@y=1\pgf@ya%
    \pgfpathlineto{\pgfpoint{\pgf@x}{\pgf@y}}
    % Line from source segment to source anchor
    \pgf@x=0\pgf@xa%
    \pgf@y=-.45\pgf@ya%
    \pgfpathmoveto{\pgfpoint{\pgf@x}{\pgf@y}}
    \pgf@x=1\pgf@xa%
    \pgf@y=-.45\pgf@ya%
    \pgfpathlineto{\pgfpoint{\pgf@x}{\pgf@y}}
    \pgf@x=1\pgf@xa%
    \pgf@y=-.45\pgf@ya%
    \pgfpathmoveto{\pgfpoint{\pgf@x}{\pgf@y}}
    \pgf@x=1\pgf@xa%
    \pgf@y=-1\pgf@ya%
    \pgfpathlineto{\pgfpoint{\pgf@x}{\pgf@y}}
    \ifpgftransistorBinvisible
    \else
      % Line from bulk segment to bulk anchor
      \pgf@x=0\pgf@xa%
      \pgf@y=0\pgf@ya%
      \pgfpathmoveto{\pgfpoint{\pgf@x}{\pgf@y}}
      \pgf@x=1\pgf@xa%
      \pgf@y=0\pgf@ya%
      \pgfpathlineto{\pgfpoint{\pgf@x}{\pgf@y}}
    \fi
    \ifpgftransistorBnotconnectedtoS
    \else
      % optionally connect bulk anchor to source anchor
      \pgf@x=1\pgf@xa%
      \pgf@y=0\pgf@ya%
      \pgfpathmoveto{\pgfpoint{\pgf@x}{\pgf@y}}
      \pgf@x=1\pgf@xa%
      \pgf@y=-1\pgf@ya%
      \pgfpathlineto{\pgfpoint{\pgf@x}{\pgf@y}}
    \fi
    % line for gate
    \pgf@x=-.4\pgf@xa%
    \pgf@y=.45\pgf@ya%
    \pgfpathmoveto{\pgfpoint{\pgf@x}{\pgf@y}}
    \pgf@x=-.4\pgf@xa%
    \pgf@y=-.45\pgf@ya%
    \pgfpathlineto{\pgfpoint{\pgf@x}{\pgf@y}}
    % Line from gate to gate anchor
    \G%
    \pgf@x=-.4\pgf@xa%
    \pgfpathmoveto{\pgfpoint{\pgf@x}{\pgf@y}}
    \G%
    \pgfpathlineto{\pgfpoint{\pgf@x}{\pgf@y}}
  }

  % Draw the arrow
  \beforebackgroundpath{
    \ifpgftransistorBinvisible
    \else
      % arrow on bulk line
      \pgf@x=0.07\pgf@xa%
      \pgf@y=0\pgf@ya%
      \pgfpathmoveto{\pgfpoint{\pgf@x}{\pgf@y}}
      \pgf@x=.6\pgf@xa%
      \pgf@y=.1\pgf@ya%
      \pgfpathlineto{\pgfpoint{\pgf@x}{\pgf@y}}
      \pgf@x=.6\pgf@xa%
      \pgf@y=-.1\pgf@ya%
      \pgfpathlineto{\pgfpoint{\pgf@x}{\pgf@y}}
      \pgfclosepath
      \pgfusepath{stroke,fill}
    \fi
  }

  \foregroundpath{
    {
      % Draw port labels
      \begingroup
      \tikzset{transistor/port labels} % Use font from this style
      \tikz@textfont

      % Set the color for the text labels
      \color{\pgfkeysvalueof{/pgf/transistor label color}}

      \pgf@anchor@nmosfet@G
      \pgftext[top,at={\pgfpoint{\pgf@x}{\pgf@y}},y=-1ex]{%
	\pgfkeysvalueof{/pgf/transistor G label}%
      }

      \pgf@anchor@nmosfet@S
      \pgftext[left,at={\pgfpoint{\pgf@x}{\pgf@y}},x=1ex]{%
	\pgfkeysvalueof{/pgf/transistor S label}%
      }

      \pgf@anchor@nmosfet@D
      \pgftext[left,at={\pgfpoint{\pgf@x}{\pgf@y}},x=1ex]{%
	\pgfkeysvalueof{/pgf/transistor D label}%
      }

      \ifpgftransistorBinvisible
      \else
	\pgf@anchor@nmosfet@B
	\pgftext[left,at={\pgfpoint{\pgf@x}{\pgf@y}},x=1ex]{%
	  \pgfkeysvalueof{/pgf/transistor B label}%
	}
      \fi

      \endgroup
      \pgfusepath{stroke}
    }
  }

}


% PMOSFET transistor shape
%
\pgfdeclareshape{pmosfet}{
  % The 'minimum width' and 'minimum height' keys, not the content, determine
  % the size
  \savedanchor\D{%
    \pgfmathsetlength\pgf@x{\pgfshapeminwidth}%
    \pgfmathsetlength\pgf@y{\pgfshapeminheight}%
    \pgf@x=0.5\pgf@x
    \pgf@y=-0.5\pgf@y
  }
  \savedanchor\G{%
    % This is redundant, but we can't call \D here:
    \pgfmathsetlength\pgf@x{\pgfshapeminwidth}%
    \pgfmathsetlength\pgf@y{\pgfshapeminheight}%
    \pgf@x=0.5\pgf@x
    \pgf@y=0.5\pgf@y
    %
    \pgf@x=-1\pgf@x%
    \ifpgftransistorGcenter
      \pgf@y=0\pgf@y%
    \else
      \ifpgftransistorGbottom
	\pgf@y=-.45\pgf@y%
      \else
	\pgf@y=.45\pgf@y%
      \fi
    \fi
  }
  \inheritanchorborder[from=nmosfet]
  \inheritanchor[from=nmosfet]{center}
  \anchor{north}{\D \pgf@x=0pt \pgf@y=-\pgf@y}
  \anchor{east}{\D \pgf@y=0pt}
  \anchor{south}{\D \pgf@x=0pt}
  \anchor{west}{\D \pgf@x=-\pgf@x \pgf@y=0pt}
  \anchor{north east}{\D \pgf@y=-\pgf@y}
  \anchor{north west}{\D \pgf@x=-\pgf@x \pgf@y=-\pgf@y}
  \anchor{south west}{\D \pgf@x=-\pgf@x}
  \anchor{south east}{\D}
  \anchor{text}{
    % put text label above the transistor:
    \D
    \pgf@x=0\pgf@x%
    \pgf@y=-1.3\pgf@y%
    % adjust for the size of the text box:
    \advance\pgf@x by -1.0\wd\pgfnodeparttextbox%
%     \advance\pgf@y by -.5\ht\pgfnodeparttextbox%
    \advance\pgf@y by 1.0\dp\pgfnodeparttextbox%
  }
  \inheritanchor[from=nmosfet]{G}
  \anchor{S}{
    \pgf@process{\D}%
    \pgf@x=1\pgf@x%
    \pgf@y=-1\pgf@y%
  }
  \anchor{D}{
    \pgf@process{\D}%
    \pgf@x=1\pgf@x%
    \pgf@y=1\pgf@y%
  }
  \inheritanchor[from=nmosfet]{B}
  \inheritbackgroundpath[from=nmosfet]
  % Draw the arrow
  \beforebackgroundpath{
    \ifpgftransistorBinvisible
    \else
      % arrow on bulk line
      \pgf@x=0.93\pgf@xa%
      \pgf@y=0\pgf@ya%
      \pgfpathmoveto{\pgfpoint{\pgf@x}{\pgf@y}}
      \pgf@x=.4\pgf@xa%
      \pgf@y=.1\pgf@ya%
      \pgfpathlineto{\pgfpoint{\pgf@x}{\pgf@y}}
      \pgf@x=.4\pgf@xa%
      \pgf@y=-.1\pgf@ya%
      \pgfpathlineto{\pgfpoint{\pgf@x}{\pgf@y}}
      \pgfclosepath
      \pgfusepath{stroke,fill}
    \fi
  }
  \foregroundpath{
    {
      % Draw port labels
      \begingroup
      \tikzset{transistor/port labels} % Use font from this style
      \tikz@textfont

      % Set the color for the text labels
      \color{\pgfkeysvalueof{/pgf/transistor label color}}

      \pgf@anchor@pmosfet@G
      \pgftext[top,at={\pgfpoint{\pgf@x}{\pgf@y}},y=-1ex]{%
	\pgfkeysvalueof{/pgf/transistor G label}%
      }

      \pgf@anchor@pmosfet@S
      \pgftext[left,at={\pgfpoint{\pgf@x}{\pgf@y}},x=1ex]{%
	\pgfkeysvalueof{/pgf/transistor S label}%
      }

      \pgf@anchor@pmosfet@D
      \pgftext[left,at={\pgfpoint{\pgf@x}{\pgf@y}},x=1ex]{%
	\pgfkeysvalueof{/pgf/transistor D label}%
      }

      \ifpgftransistorBinvisible
      \else
	\pgf@anchor@pmosfet@B
	\pgftext[left,at={\pgfpoint{\pgf@x}{\pgf@y}},x=1ex]{%
	  \pgfkeysvalueof{/pgf/transistor B label}%
	}
      \fi

      \endgroup
      \pgfusepath{stroke}
    }
  }
}


\endinput
