% Copyright 2017-2020 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: 16 January 2020

\usetikzlibrary{intersections}


% a template for usage, with all the options:
%
% \usepgflibrary{shapes.gates.jb.logic}
% % This file, pgflibraryshapes.gates.jb.logic.code.tex, needs to
% % be in the search path, e.g., in the current directory.
% ....
%
% \node [mux2to1,%
% 	% mux2to1 bottom S,%
% 	mux2to1 input 0 label=0,%
% 	mux2to1 input 1 label=1,%
% 	mux2to1 S label=,%
% 	mux2to1 output label=,%
% 	% mux2to1 port labels style=,%
% 	% draw=red,
% 	% fill=yellow,
%   ] (mux) at (0,0) {};
%
% \node [bufce,%
% 	% bufce bottom CE,%
%       % bufce input label=I,%
%       % bufce CE label=CE,%
%       % bufce output label=O,%
% 	% bufce port labels style=,%
% 	% draw=red,
% 	% fill=yellow,
%   ] (bufce) at (0,0) {};

% Define variant switches and default text labels inside mux2to1
\pgfkeys{/pgf/.cd,
	mux2to1 bottom S/.is if=pgfmuxTwoToOneBottomS,%
	mux2to1 input 0 label/.initial=0,%
	mux2to1 input 1 label/.initial=1,%
	mux2to1 S label/.initial=,% (empty)
	mux2to1 output label/.initial=,% (empty)
	mux2to1 port labels style/.initial={\sffamily\scriptsize},%
}

% Define variant switches and default text labels inside bufce
\pgfkeys{/pgf/.cd,
	bufce bottom CE/.is if=pgfbufceBottomCE,%
	bufce input label/.initial=,% (empty)
	bufce CE label/.initial=,% (empty)
	bufce output label/.initial=,% (empty)
	bufce port labels style/.initial={\sffamily\scriptsize},%
}

% Default sizes of the shape mux2to1
\tikzset{every mux2to1 node/.style={%
	draw,%
	minimum width=.61cm,%
	minimum height=0.98cm,%
	% thick,%
	inner sep=1mm,%
	outer sep=0pt,%
	cap=round,%
	add font=\sffamily,%
	},%
}

% Default sizes of the shape bufce
\tikzset{every bufce node/.style={%
	draw,%
	minimum width=.61cm,%
	minimum height=0.98cm,%
	% 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\ifpgfmuxTwoToOneBottomS

\newif\ifpgfbufceBottomCE

% An auxiliary function for drawing the shape of mux2to1
% 
\def\pgf@muxTwoToOne@backgroundpath{%
  \northeast
  \pgf@xc=\pgf@x % half x size of bounding box of mux
  \pgf@yc=\pgf@y  % half y size of bounding box of mux
  \pgf@x=-\pgf@xc%
  \pgfpathmoveto{\pgfpoint{\pgf@x}{\pgf@y}}
  \pgf@x=\pgf@xc%
  \pgf@y=\pgf@yc%
  \advance\pgf@y by -.5\pgf@xc%
  \pgfpathlineto{\pgfpoint{\pgf@x}{\pgf@y}}
  \pgf@x=\pgf@xc%
  \pgf@y=-\pgf@yc%
  \advance\pgf@y by .5\pgf@xc%
  \pgfpathlineto{\pgfpoint{\pgf@x}{\pgf@y}}
  \pgf@x=-\pgf@xc%
  \pgf@y=-\pgf@yc%
  \pgfpathlineto{\pgfpoint{\pgf@x}{\pgf@y}}
  \pgfpathclose
}

% Shape mux2to1
%
\pgfdeclareshape{mux2to1}{
  % The 'minimum width' and 'minimum height' keys, not the content, determine
  % the size.
  % This (also) is needed for \inheritanchorborder from rectangle:
  \savedanchor\southwest{%
    \pgfmathsetlength\pgf@x{\pgfshapeminwidth}%
    \pgfmathsetlength\pgf@y{\pgfshapeminheight}%
    \pgf@x=-0.5\pgf@x
    \pgf@y=-0.5\pgf@y
  }
  % This (also) is needed for \inheritanchorborder from rectangle:
  \savedanchor\northeast{%
    \pgfmathsetlength\pgf@x{\pgfshapeminwidth}%
    \pgfmathsetlength\pgf@y{\pgfshapeminheight}%
    \pgf@x=0.5\pgf@x
    \pgf@y=0.5\pgf@y
  }
  % The following must be saved anchor in order that the
  % "if" is defined:
  \savedanchor\S{%
    \pgfmathsetlength\pgf@x{\pgfshapeminwidth}%
    \pgfmathsetlength\pgf@y{\pgfshapeminheight}%
    \ifpgfmuxTwoToOneBottomS
      \advance\pgf@y by -1.5\pgf@y%
      \advance\pgf@y by .125\pgf@x%
    \else
      \advance\pgf@y by -.5\pgf@y%
      \advance\pgf@y by -.125\pgf@x%
    \fi
    \pgf@x=0pt
  }

  % For simplicity, we inherit the shape for the border anchors
  % from rectangle. This is *incorrect* for the slanted upper and
  % lower lines of the shape.
  % TODO: make \anchorborder work. It can use
  % \pgf@muxTwoToOne@backgroundpath. But I didn't manage to find
  % out how to account for the coordinate transformations that appear
  % to happen before and after \pgfintersectionofpaths{}{}.
  \inheritanchorborder[from=rectangle]

%   % Compute the point where the straight line from the center to the
%   % point specified by \pgf@x and \pgf@y intersects the border of
%   % the shape. The result is returned in \pgf@x and \pgf@y.
%   \anchorborder{%
%     \pgf@xc=\pgf@x
%     \pgf@yc=\pgf@y
%     \pgfintersectionofpaths{%
%       \pgf@process{%
% 	\pgf@muxTwoToOne@backgroundpath
%       }
%     }{%
%       \pgf@process{%
% 	\pgfpointorigin
%       }
%       \pgfpathlineto{\pgfpoint{\pgf@xc}{\pgf@yc}}
%     }
%     \pgfpointintersectionsolution{1}
% %     \pgf@x=0pt
% %     \pgf@y=0pt
%   }

  % Define same anchor a normal rectangle has
  \anchor{center}{\pgfpointorigin}
  \anchor{north}{\northeast \pgf@x=0pt}
  \anchor{east}{\northeast \pgf@y=0pt}
  \anchor{south}{\southwest \pgf@x=0pt}
  \anchor{west}{\southwest \pgf@y=0pt}
  \anchor{north east}{\northeast}
  \anchor{north west}{\northeast \pgf@x=-\pgf@x}
  \anchor{south west}{\southwest}
  \anchor{south east}{\southwest \pgf@x=-\pgf@x}
  \anchor{text}{
    \pgfpointorigin
    \advance\pgf@x by -.5\wd\pgfnodeparttextbox%
    \advance\pgf@y by -.5\ht\pgfnodeparttextbox%
    \advance\pgf@y by +.5\dp\pgfnodeparttextbox%
  }

  % Define the input and output anchors
  \anchor{input 0}{\northeast \pgf@x=-\pgf@x \pgf@y=.5\pgf@y}
  \anchor{input 1}{\northeast \pgf@x=-\pgf@x \pgf@y=-.5\pgf@y}
  \anchor{S}{\S}
  \anchor{output}{\northeast \pgf@y=0pt}

  % Draw the outline of the mux
  \backgroundpath{
    % The color of the following is the one set with "draw=...",
    % and it will be filled with whatever is set by "fill=...".
    \pgf@muxTwoToOne@backgroundpath
  }

  % Draw port labels
  \beforebackgroundpath{
    \begingroup
    % Set the color for the text labels, independently of fill color
    % which otherwise would be used.
    % TODO: This shouldn't be hard-coded. Instead, we should use the
    % color of the node text. How to do it?
    \color{black}

    \northeast
    \pgf@xc=\pgf@x % half x size of bounding box of mux
    \pgf@yc=\pgf@y  % half y size of bounding box of mux
    \pgf@x=-\pgf@x
    \advance\pgf@y by -.5\pgf@yc%
    \pgftext[left,base,at={\pgfpoint{\pgf@x}{\pgf@y}},x=\pgfshapeinnerxsep]{%
      \pgfkeysvalueof{/pgf/mux2to1 port labels style}%
      \raisebox{-0.75ex}{\pgfkeysvalueof{/pgf/mux2to1 input 0 label}}%
    }
    \pgf@x=-\pgf@xc
    \pgf@y=\pgf@yc
    \advance\pgf@y by -1.5\pgf@yc%
    \pgftext[left,base,at={\pgfpoint{\pgf@x}{\pgf@y}},x=\pgfshapeinnerxsep]{%
      \pgfkeysvalueof{/pgf/mux2to1 port labels style}%
      \raisebox{-0.75ex}{\pgfkeysvalueof{/pgf/mux2to1 input 1 label}}%
    }
    \pgf@x=\pgf@xc
    \pgf@y=0pt
    \pgftext[right,base,at={\pgfpoint{\pgf@x}{\pgf@y}},x=-\pgfshapeinnerxsep]{%
      \pgfkeysvalueof{/pgf/mux2to1 port labels style}%
      \raisebox{-0.75ex}{\pgfkeysvalueof{/pgf/mux2to1 output label}}%
    }
    \S
    \ifpgfmuxTwoToOneBottomS
      \pgftext[bottom,at={\pgfpoint{\pgf@x}{\pgf@y}},y=\pgfshapeinnerysep]{%
	\pgfkeysvalueof{/pgf/mux2to1 port labels style}%
	\pgfkeysvalueof{/pgf/mux2to1 S label}%
      }
    \else
      \pgftext[top,at={\pgfpoint{\pgf@x}{\pgf@y}},y=-\pgfshapeinnerysep]{%
	\pgfkeysvalueof{/pgf/mux2to1 port labels style}%
	\pgfkeysvalueof{/pgf/mux2to1 S label}%
      }
    \fi
    \endgroup
    \pgfusepath{stroke}
  }
}



% An auxiliary function for drawing the shape of bufce
% 
\def\pgf@bufce@backgroundpath{%
  \northeast
  \pgf@xc=\pgf@x % half x size of bounding box of bufce
  \pgf@yc=\pgf@y  % half y size of bounding box of bufce
  \pgf@x=-\pgf@xc%
  \pgfpathmoveto{\pgfpoint{\pgf@x}{\pgf@y}}
  \pgf@x=\pgf@xc%
  \pgf@y=0pt%
  \pgfpathlineto{\pgfpoint{\pgf@x}{\pgf@y}}
  \pgf@x=-\pgf@xc%
  \pgf@y=-\pgf@yc%
  \pgfpathlineto{\pgfpoint{\pgf@x}{\pgf@y}}
  \pgfpathclose
}

% Shape bufce
%
\pgfdeclareshape{bufce}{
  % The 'minimum width' and 'minimum height' keys, not the content, determine
  % the size.
  % This (also) is needed for \inheritanchorborder from isoceles triangle:
  \savedanchor\southwest{%
    \pgfmathsetlength\pgf@x{\pgfshapeminwidth}%
    \pgfmathsetlength\pgf@y{\pgfshapeminheight}%
    \pgf@x=-0.5\pgf@x
    \pgf@y=-0.5\pgf@y
  }
  % This (also) is needed for \inheritanchorborder from isoceles triangle:
  \savedanchor\northeast{%
    \pgfmathsetlength\pgf@x{\pgfshapeminwidth}%
    \pgfmathsetlength\pgf@y{\pgfshapeminheight}%
    \pgf@x=0.5\pgf@x
    \pgf@y=0.5\pgf@y
  }
  % The following must be saved anchor in order that the
  % "if" is defined:
  \savedanchor\CE{%
    \pgfmathsetlength\pgf@x{\pgfshapeminwidth}%
    \pgfmathsetlength\pgf@y{\pgfshapeminheight}%
    % Because it looks nicer, the anchor is a little bit away from the
    % narrow end of the buffer:
    \pgf@x=-0.10\pgf@x
    \ifpgfbufceBottomCE
      % Since the anchor is at 20% of the distance from the middle to
      % the left, it must be adjusted vertically by 20% of 0.25\pgf@y,
      % which results in a value of 0.30\pgf@y.
      \pgf@y=-0.30\pgf@y
    \else
      \pgf@y=0.30\pgf@y
    \fi
  }

  % For simplicity, we inherit the shape for the border anchors
  % from isoceles triangle.
  \inheritanchorborder[from=isoceles triangle]

%   % Compute the point where the straight line from the center to the
%   % point specified by \pgf@x and \pgf@y intersects the border of
%   % the shape. The result is returned in \pgf@x and \pgf@y.
%   \anchorborder{%
%     \pgf@xc=\pgf@x
%     \pgf@yc=\pgf@y
%     \pgfintersectionofpaths{%
%       \pgf@process{%
% 	\pgf@bufce@backgroundpath
%       }
%     }{%
%       \pgf@process{%
% 	\pgfpointorigin
%       }
%       \pgfpathlineto{\pgfpoint{\pgf@xc}{\pgf@yc}}
%     }
%     \pgfpointintersectionsolution{1}
% %     \pgf@x=0pt
% %     \pgf@y=0pt
%   }

  % Define same anchor a normal isoceles triangle has
  \anchor{center}{\pgfpointorigin}
  \anchor{north}{\northeast \pgf@x=0pt}
  \anchor{east}{\northeast \pgf@y=0pt}
  \anchor{south}{\southwest \pgf@x=0pt}
  \anchor{west}{\southwest \pgf@y=0pt}
  \anchor{north east}{\northeast}
  \anchor{north west}{\northeast \pgf@x=-\pgf@x}
  \anchor{south west}{\southwest}
  \anchor{south east}{\southwest \pgf@x=-\pgf@x}
  \anchor{text}{
    \pgfpointorigin
    \advance\pgf@x by -.5\wd\pgfnodeparttextbox%
    \advance\pgf@y by -.5\ht\pgfnodeparttextbox%
    \advance\pgf@y by +.5\dp\pgfnodeparttextbox%
  }

  % Define the input and output anchors
  \anchor{input}{\northeast \pgf@x=-\pgf@x \pgf@y=0pt}
  \anchor{CE}{\CE}
  \anchor{output}{\northeast \pgf@y=0pt}

  % Draw the outline of the bufce
  \backgroundpath{
    % The color of the following is the one set with "draw=...",
    % and it will be filled with whatever is set by "fill=...".
    \pgf@bufce@backgroundpath
  }

  % Draw port labels
  \beforebackgroundpath{
    \begingroup
    % Set the color for the text labels, independently of fill color
    % which otherwise would be used.
    % TODO: This shouldn't be hard-coded. Instead, we should use the
    % color of the node text. How to do it?
    \color{black}

    \northeast
    \pgf@xc=\pgf@x % half x size of bounding box of bufce
    \pgf@yc=\pgf@y  % half y size of bounding box of bufce
    \pgf@x=-\pgf@x
    \pgf@y=0pt
    \pgftext[left,base,at={\pgfpoint{\pgf@x}{\pgf@y}},x=\pgfshapeinnerxsep]{%
      \pgfkeysvalueof{/pgf/bufce port labels style}%
      \raisebox{-0.75ex}{\pgfkeysvalueof{/pgf/bufce input label}}%
    }
    \pgf@x=\pgf@xc
    \pgf@y=0pt
    \pgftext[right,base,at={\pgfpoint{\pgf@x}{\pgf@y}},x=-\pgfshapeinnerxsep]{%
      \pgfkeysvalueof{/pgf/bufce port labels style}%
      \raisebox{-0.75ex}{\pgfkeysvalueof{/pgf/bufce output label}}%
    }
    \CE
    \ifpgfbufceBottomCE
      \pgftext[bottom,at={\pgfpoint{\pgf@x}{\pgf@y}},y=\pgfshapeinnerysep]{%
	\pgfkeysvalueof{/pgf/bufce port labels style}%
	\pgfkeysvalueof{/pgf/bufce CE label}%
      }
    \else
      \pgftext[top,at={\pgfpoint{\pgf@x}{\pgf@y}},y=-\pgfshapeinnerysep]{%
	\pgfkeysvalueof{/pgf/bufce port labels style}%
	\pgfkeysvalueof{/pgf/bufce CE label}%
      }
    \fi
    \endgroup
    \pgfusepath{stroke}
  }
}


\endinput
