6

If TikZ has them it can't be all that difficult.

\documentclass{standalone}
\usepackage{circuitikz}
\makeatother
\begin{document}
\begin{circuitikz}
\node[american and port] at (0,0) {};
\node[american nand port] at (0,-2) {};
\node[american or port] at (2,0) {};
\node[american nor port] at (2,-2) {};
\node[american xor port] at (4,0) {};
\node[american xnor port] at (4,-2) {};
\end{circuitikz}
\end{document}

mwe

John Kormylo
  • 79,712
  • 3
  • 50
  • 120

3 Answers3

9

TikZ uses \pgfutil@g@addto@macro to create anchors, which are presumably saved as global macros with some undocumented naming convention. The key seems to be writing a macro (\pgf@circ@logicport@input) which will locate the anchors using only \savedanchors and one input (\pgfmathcounter).

Another problem is that the left side of various ports are curved, so one needs to be able to compute the edge location for a given y value. To simplify these computations, I used arcs instead of \pgfpathcurveto. I replaced the outer curves as well. The new shapes are not perfect matches, but they are very close. To define the left side arcs I added two new parameters, angle and inner. angle is the starting angle, and inner is the distance from the outer edge to the middle of the curve. The x and y radii are computed using \pgfmath. (Eventually I ran out of length registers and had to use macros.) OTOH, all the aaa through ddd parameters are no longer used.

As is custom for Circuitikz, one can set the number of inputs (inputs) for each type of gate using \ctikzset. I added a node parameter (number inputs) which can be set on a node by node basis. Also, this number can never be less than 2 or greater than 16.

I added origin parameter. Setting origin=0 puts the center anchor in the center of the node. The default setting is 0.8 for backward compatibility. I fixed the text anchor so that one can write part numbers etc. inside the port (if it fits).

\documentclass{standalone}
\usepackage{circuitikz}

\ctikzset{tripoles/american and port/origin/.initial=0.8}
\ctikzset{tripoles/american and port/inputs/.initial=2}

\ctikzset{tripoles/american nand port/origin/.initial=0.8}
\ctikzset{tripoles/american nand port/inputs/.initial=2}

\ctikzset{tripoles/american nor port/origin/.initial=0.8}
\ctikzset{tripoles/american nor port/inputs/.initial=2}
\ctikzset{tripoles/american nor port/angle/.initial=70}
\ctikzset{tripoles/american nor port/inner/.initial=0.3}

\ctikzset{tripoles/american or port/origin/.initial=0.8}
\ctikzset{tripoles/american or port/inputs/.initial=2}
\ctikzset{tripoles/american or port/angle/.initial=70}
\ctikzset{tripoles/american or port/inner/.initial=0.3}

\ctikzset{tripoles/american xor port/origin/.initial=0.8}
\ctikzset{tripoles/american xor port/inputs/.initial=2}
\ctikzset{tripoles/american xor port/angle/.initial=70}
\ctikzset{tripoles/american xor port/inner/.initial=0.3}

\ctikzset{tripoles/american xnor port/origin/.initial=0.8}
\ctikzset{tripoles/american xnor port/inputs/.initial=2}
\ctikzset{tripoles/american xnor port/angle/.initial=70}
\ctikzset{tripoles/american xnor port/inner/.initial=0.3}

\pgfkeys{/tikz/number inputs/.initial=0}
\pgfkeys{/tikz/number inputs/.default=0}

\makeatletter
\newcount{\pgf@circ@res@count}% reserve global register

\newcommand{\pgf@circ@logicport@input}[1]% #1 = \pgfmathcounter
{%
  \pgfextracty{\pgf@circ@res@up}{\northeast}%
  \step
  \pgf@circ@res@step=\dimexpr 2\pgf@y -2\pgf@circ@res@up\relax
  \advance\pgf@y by -#1\pgf@circ@res@step\relax
}%
\long\def\pgfcircdeclarelogicport#1#2{%
    \pgfdeclareshape{american #1 port}%
    {%
    \savedmacro\resize{% automatic
      \pgf@circ@res@up = \pgfkeysvalueof{/tikz/circuitikz/tripoles/american #1 port/height}\pgf@circ@Rlen
      \pgf@circ@res@up = .5\pgf@circ@res@up
      \pgf@circ@res@down = -\pgf@circ@res@up
      \pgf@circ@res@right = \pgfkeysvalueof{/tikz/circuitikz/tripoles/american #1 port/width}\pgf@circ@Rlen
      \pgf@circ@res@right = .5\pgf@circ@res@right
      \pgf@circ@res@left = -\pgf@circ@res@right
    }%
    \savedmacro\inputs{% get number of inputs
      \pgf@circ@res@count=\pgfkeysvalueof{/tikz/number inputs}\relax%
      \ifnum\pgf@circ@res@count=0
        \pgf@circ@res@count=\pgfkeysvalueof{/tikz/circuitikz/tripoles/american #1 port/inputs}\relax%
      \fi
      \ifnum\pgf@circ@res@count<2 \pgf@circ@res@count=2\fi
      \ifnum\pgf@circ@res@count>16 \pgf@circ@res@count=16\fi
      \def\inputs{\the\pgf@circ@res@count}%
    }%
    \savedanchor\step{% 1/2 gap at edges
      \pgf@circ@res@step = \pgfkeysvalueof{/tikz/circuitikz/tripoles/american #1 port/height}\pgf@circ@Rlen
      \divide\pgf@circ@res@step by \pgf@circ@res@count
      \pgfpoint{\pgf@circ@res@left}{\dimexpr\pgf@circ@res@up+0.5\pgf@circ@res@step}%
    }%
      \savedanchor\northeast{\pgfpoint{\pgf@circ@res@right}{\pgf@circ@res@up}}
    \savedanchor\southwest{\pgfpoint{\pgf@circ@res@left}{\pgf@circ@res@down}}
    \savedanchor\left{\pgfpoint{\pgfkeysvalueof{/tikz/circuitikz/tripoles/american #1 port/port width}\pgf@circ@res@left}{0pt}}
    \savedanchor\right{\pgfpoint{\pgfkeysvalueof{/tikz/circuitikz/tripoles/american #1 port/port width}\pgf@circ@res@right}{0pt}}
    \savedanchor\origin{\pgfpoint{\pgfkeysvalueof{/tikz/circuitikz/tripoles/american #1 port/origin}\pgf@circ@res@right}{0pt}}

    \anchor{center}{\origin}% for backwards compatibility
    \anchor{text}{\pgfpoint{-.5\wd\pgfnodeparttextbox}{\dimexpr.5\dp\pgfnodeparttextbox-.5\ht\pgfnodeparttextbox}}

% create input anchors
    \expandafter\pgfutil@g@addto@macro\csname pgf@sh@s@american #1 port\endcsname{%
      \pgfmathloop%
      \ifnum\pgfmathcounter>\pgf@circ@res@count%
      \else%
        %\pgfutil@ifundefined{pgf@anchor@american #1 port@in \pgfmathcounter}{%
          \expandafter\xdef\csname pgf@anchor@american #1 port@in \pgfmathcounter\endcsname{%
            \noexpand\pgf@circ@logicport@input{\pgfmathcounter}% defined above
          }%
        %}{}%
      \repeatpgfmathloop%
    }

      \anchor{out}{\pgfpoint{\pgf@circ@res@right}{0pt}}

    \anchor{left}{\left}% edges of component mius leads
    \anchor{right}{\right}

    \anchor{north east}{\northeast}% see \Compass macro
    \anchor{south west}{\southwest}
    \anchor{north}{\pgfextracty{\pgf@circ@res@up}{\northeast}%
      \pgfpoint{0cm}{\pgf@circ@res@up}}
    \anchor{north west}{\pgfextracty{\pgf@circ@res@up}{\northeast}%
      \pgfextractx{\pgf@circ@res@left}{\southwest}%
      \pgfpoint{\pgf@circ@res@left}{\pgf@circ@res@up}}
    \anchor{west}{\pgfextractx{\pgf@circ@res@left}{\sosuthwest}%
      \pgfpoint{\pgf@circ@res@left}{0cm}}
    \anchor{south}{\pgfextracty{\pgf@circ@res@down}{\southwest}%
      \pgfpoint{0cm}{\pgf@circ@res@down}}
    \anchor{south east}{\pgfextracty{\pgf@circ@res@down}{\southwest}%
      \pgfextractx{\pgf@circ@res@right}{\northeast}%
      \pgfpoint{\pgf@circ@res@right}{\pgf@circ@res@down}}
    \anchor{east}{\pgfextractx{\pgf@circ@res@right}{\northeast}%
      \pgfpoint{\pgf@circ@res@right}{0cm}}

      \backgroundpath{          
            \pgfsetcolor{\pgfkeysvalueof{/tikz/circuitikz/color}}   
            #2
      }
    }
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% and %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\pgfcircdeclarelogicport{and}{
  \pgfextracty{\pgf@circ@res@temp}{\step}%
  \pgf@circ@res@step = \dimexpr 2\pgf@circ@res@temp -2\pgf@circ@res@up\relax
  \pgf@circ@res@count = \inputs\relax
  \loop\ifnum\pgf@circ@res@count>0
    \advance\pgf@circ@res@temp by -\pgf@circ@res@step
      \pgfpathmoveto{\pgfpoint{\pgf@circ@res@left}{\pgf@circ@res@temp}}%
    \pgfpathlineto{\pgfpoint
        {\pgfkeysvalueof{/tikz/circuitikz/tripoles/american and port/port width}\pgf@circ@res@left}
        {\pgf@circ@res@temp}}
    \advance\pgf@circ@res@count by -1
  \repeat

    \pgfpathmoveto{\pgfpoint{\pgf@circ@res@right}{0pt}}
    \pgfpathlineto{\pgfpoint
        {\pgfkeysvalueof{/tikz/circuitikz/tripoles/american and port/port width}\pgf@circ@res@right}
        {0pt}}

    \pgfusepath{draw}

    \pgfsetlinewidth{2\pgflinewidth}
  \pgf@circ@res@other=\pgfkeysvalueof{/tikz/circuitikz/tripoles/american and port/port width}\pgf@circ@res@left

    \pgfpathmoveto{\pgfpoint{\pgf@circ@res@other}{\pgf@circ@res@up}}
  \pgfpathlineto{\pgfpoint{\pgf@circ@res@other}{\pgf@circ@res@down}}
  \pgfpatharc{-90}{90}{-2\pgf@circ@res@other and \pgf@circ@res@up}
  \pgfpathclose
    \pgfusepath{draw}
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% nand %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\pgfcircdeclarelogicport{nand}{
    \pgfextracty{\pgf@circ@res@temp}{\step}%
  \pgf@circ@res@step = \dimexpr 2\pgf@circ@res@temp -2\pgf@circ@res@up\relax
  \pgf@circ@res@count = \inputs\relax
  \loop\ifnum\pgf@circ@res@count>0
    \advance\pgf@circ@res@temp by -\pgf@circ@res@step
      \pgfpathmoveto{\pgfpoint{\pgf@circ@res@left}{\pgf@circ@res@temp}}%
    \pgfpathlineto{\pgfpoint
        {\pgfkeysvalueof{/tikz/circuitikz/tripoles/american nand port/port width}\pgf@circ@res@left}
        {\pgf@circ@res@temp}}
    \advance\pgf@circ@res@count by -1
  \repeat

    \pgfpathmoveto{\pgfpoint{\pgf@circ@res@right}{0pt}}
    \pgfpathlineto{\pgfpoint
        {\pgfkeysvalueof{/tikz/circuitikz/tripoles/american nand port/port width}\pgf@circ@res@right}
        {0pt}}

    \pgfusepath{draw}

    \pgfsetlinewidth{2\pgflinewidth}
    \pgf@circ@res@step = \pgfkeysvalueof{/tikz/circuitikz/tripoles/american nand port/circle width}\pgf@circ@res@right
    \pgf@circ@res@other = \pgfkeysvalueof{/tikz/circuitikz/tripoles/american nand port/port width}\pgf@circ@res@right
  \pgf@circ@res@temp = \dimexpr 2\pgf@circ@res@other - \pgf@circ@res@step\relax

    \pgfpathmoveto{\pgfpoint{-\pgf@circ@res@other}{\pgf@circ@res@up}}
    \pgfpathlineto{\pgfpoint{-\pgf@circ@res@other}{\pgf@circ@res@down}}
  \pgfpatharc{-90}{90}{\pgf@circ@res@temp and \pgf@circ@res@up}
  \pgfpathclose

    \pgfpathellipse
        {\pgfpoint{\pgf@circ@res@other-.5\pgf@circ@res@step}{0pt}}
        {\pgfpoint{.5\pgf@circ@res@step}{0pt}}
        {\pgfpoint{0pt}{.5\pgf@circ@res@step}}

    \pgfusepath{draw}
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% nor %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\pgfcircdeclarelogicport{nor}{
  \edef\pgf@circ@math@angle{\pgfkeysvalueof{/tikz/circuitikz/tripoles/american nor port/angle}}%
  \pgf@circ@res@other=\pgfkeysvalueof{/tikz/circuitikz/tripoles/american nor port/inner}\pgf@circ@res@right
  \pgfmathsetlengthmacro{\pgf@circ@math@xradius}{\pgf@circ@res@other /(1 - cos(\pgf@circ@math@angle)}%
  \pgfmathsetlengthmacro{\pgf@circ@math@yradius}{\pgf@circ@res@up /sin(\pgf@circ@math@angle)}%
  \pgf@circ@res@other=\pgfkeysvalueof{/tikz/circuitikz/tripoles/american nor port/port width}\pgf@circ@res@right
  \pgfmathsetlengthmacro{\pgf@circ@math@xorigin}{\pgf@circ@res@other + \pgf@circ@math@xradius*cos(\pgf@circ@math@angle)}%

    \pgfextracty{\pgf@circ@res@temp}{\step}%
  \pgf@circ@res@step = \dimexpr 2\pgf@circ@res@temp -2\pgf@circ@res@up\relax
  \pgf@circ@res@count = \inputs\relax
  \loop\ifnum\pgf@circ@res@count>0
    \advance\pgf@circ@res@temp by -\pgf@circ@res@step
      \pgfpathmoveto{\pgfpoint{\pgf@circ@res@left}{\pgf@circ@res@temp}}%
    \pgfmathsetmacro{\pgf@circ@math@angle}{asin(\pgf@circ@res@temp/\pgf@circ@math@yradius)}%
    \pgfmathsetlength{\pgf@circ@res@other}{\pgf@circ@math@xradius*cos(\pgf@circ@math@angle)-\pgf@circ@math@xorigin}%
    \pgfpathlineto{\pgfpoint{\pgf@circ@res@other}{\pgf@circ@res@temp}}%
    \advance\pgf@circ@res@count by -1
  \repeat

  \pgf@circ@res@other=\pgfkeysvalueof{/tikz/circuitikz/tripoles/american nor port/port width}\pgf@circ@res@right
    \pgfpathmoveto{\pgfpoint{\pgf@circ@res@right}{0pt}}
    \pgfpathlineto{\pgfpoint{\pgf@circ@res@other}{0pt}}

  \pgfusepath{draw}

  \pgfsetlinewidth{2\pgflinewidth}

  \edef\pgf@circ@math@angle{\pgfkeysvalueof{/tikz/circuitikz/tripoles/american nor port/angle}}%
    \pgf@circ@res@step = \pgfkeysvalueof{/tikz/circuitikz/tripoles/american nor port/circle width}\pgf@circ@res@right
  \pgf@circ@res@temp = \dimexpr 2\pgf@circ@res@other - \pgf@circ@res@step\relax
  \advance\pgf@circ@res@other by -\pgf@circ@res@step

  \pgfpathmoveto{\pgfpoint{\pgf@circ@res@other}{0pt}}% for symmetry
  \pgfpatharc{0}{90}{\pgf@circ@res@temp and \pgf@circ@res@up}%
  \pgfpatharc{\pgf@circ@math@angle}{-\pgf@circ@math@angle}{\pgf@circ@math@xradius and \pgf@circ@math@yradius}%
  \pgfpatharc{-90}{0}{\pgf@circ@res@temp and \pgf@circ@res@up}%
  \pgfpathclose

    \pgfpathellipse
        {\pgfpoint{\pgf@circ@res@other+.5\pgf@circ@res@step}{0pt}}
        {\pgfpoint{.5\pgf@circ@res@step}{0pt}}
        {\pgfpoint{0pt}{.5\pgf@circ@res@step}}

    \pgfusepath{draw}
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% or %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\pgfcircdeclarelogicport{or}{
    \edef\pgf@circ@math@angle{\pgfkeysvalueof{/tikz/circuitikz/tripoles/american or port/angle}}%
  \pgf@circ@res@other=\pgfkeysvalueof{/tikz/circuitikz/tripoles/american or port/inner}\pgf@circ@res@right
  \pgfmathsetlengthmacro{\pgf@circ@math@xradius}{\pgf@circ@res@other /(1 - cos(\pgf@circ@math@angle)}%
  \pgfmathsetlengthmacro{\pgf@circ@math@yradius}{\pgf@circ@res@up /sin(\pgf@circ@math@angle)}%
  \pgf@circ@res@other=\pgfkeysvalueof{/tikz/circuitikz/tripoles/american or port/port width}\pgf@circ@res@right
  \pgfmathsetlengthmacro{\pgf@circ@math@xorigin}{\pgf@circ@res@other + \pgf@circ@math@xradius*cos(\pgf@circ@math@angle)}%

    \pgfextracty{\pgf@circ@res@temp}{\step}%
  \pgf@circ@res@step = \dimexpr 2\pgf@circ@res@temp -2\pgf@circ@res@up\relax
  \pgf@circ@res@count = \inputs\relax
  \loop\ifnum\pgf@circ@res@count>0
    \advance\pgf@circ@res@temp by -\pgf@circ@res@step
      \pgfpathmoveto{\pgfpoint{\pgf@circ@res@left}{\pgf@circ@res@temp}}%
    \pgfmathsetmacro{\pgf@circ@math@angle}{asin(\pgf@circ@res@temp/\pgf@circ@math@yradius)}%
    \pgfmathsetlength{\pgf@circ@res@other}{\pgf@circ@math@xradius*cos(\pgf@circ@math@angle)-\pgf@circ@math@xorigin}%
    \pgfpathlineto{\pgfpoint{\pgf@circ@res@other}{\pgf@circ@res@temp}}%
    \advance\pgf@circ@res@count by -1
  \repeat

  \pgf@circ@res@other=\pgfkeysvalueof{/tikz/circuitikz/tripoles/american or port/port width}\pgf@circ@res@right
    \pgfpathmoveto{\pgfpoint{\pgf@circ@res@right}{0pt}}
    \pgfpathlineto{\pgfpoint{\pgf@circ@res@other}{0pt}}

  \pgfusepath{draw}

  \pgfsetlinewidth{2\pgflinewidth}

  \edef\pgf@circ@math@angle{\pgfkeysvalueof{/tikz/circuitikz/tripoles/american or port/angle}}%

  \pgfpathmoveto{\pgfpoint{\pgf@circ@res@other}{0pt}}% for symmetry
  \pgfpatharc{0}{90}{2\pgf@circ@res@other and \pgf@circ@res@up}%
  \pgfpatharc{\pgf@circ@math@angle}{-\pgf@circ@math@angle}{\pgf@circ@math@xradius and \pgf@circ@math@yradius}%
  \pgfpatharc{-90}{0}{2\pgf@circ@res@other and \pgf@circ@res@up}%
  \pgfpathclose

    \pgfusepath{draw}
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% xor %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\pgfcircdeclarelogicport{xor}{
  \pgfkeysgetvalue{/tikz/circuitikz/tripoles/american xor port/angle}{\pgf@circ@math@angle}%
  \pgf@circ@res@other=\pgfkeysvalueof{/tikz/circuitikz/tripoles/american xor port/inner}\pgf@circ@res@right
  \pgfmathsetlengthmacro{\pgf@circ@math@xradius}{\pgf@circ@res@other /(1 - cos(\pgf@circ@math@angle)}%
  \pgfmathsetlengthmacro{\pgf@circ@math@yradius}{\pgf@circ@res@up / sin(\pgf@circ@math@angle))}%
  \pgf@circ@res@other=\pgfkeysvalueof{/tikz/circuitikz/tripoles/american xor port/port width}\pgf@circ@res@right
  \pgfmathsetlengthmacro{\pgf@circ@math@xorigin}{\pgf@circ@res@other + \pgf@circ@math@xradius*cos(\pgf@circ@math@angle)}%
  \pgf@circ@res@temp=\pgfkeysvalueof{/tikz/circuitikz/tripoles/american xor port/distance}\pgf@circ@res@right
  \pgfmathsetlengthmacro{\pgf@circ@math@distance}{\pgf@circ@res@temp}
% this compensates for the effect of the line width on the gap between the arcs
  \pgfmathsetlengthmacro{\pgf@circ@math@yradiusA}{\pgf@circ@math@yradius -2\pgflinewidth}%
  \pgfmathsetlengthmacro{\pgf@circ@math@xradiusA}{\pgf@circ@math@xradius -2\pgflinewidth}%

    \pgfextracty{\pgf@circ@res@temp}{\step}%
  \pgf@circ@res@step = \dimexpr 2\pgf@circ@res@temp -2\pgf@circ@res@up\relax
  \pgf@circ@res@count = \inputs\relax
  \loop\ifnum\pgf@circ@res@count>0
    \advance\pgf@circ@res@temp by -\pgf@circ@res@step
      \pgfpathmoveto{\pgfpoint{\pgf@circ@res@left}{\pgf@circ@res@temp}}%
    \pgfmathsetmacro{\pgf@circ@math@angle}{asin(\pgf@circ@res@temp  / \pgf@circ@math@yradiusA)}%
    \pgfmathsetlength{\pgf@circ@res@other}{\pgf@circ@math@xradiusA*cos(\pgf@circ@math@angle)-\pgf@circ@math@xorigin}%
    \advance\pgf@circ@res@other by -\pgf@circ@math@distance
    \pgfpathlineto{\pgfpoint{\pgf@circ@res@other}{\pgf@circ@res@temp}}%
    \advance\pgf@circ@res@count by -1
  \repeat

    \pgf@circ@res@other=\pgfkeysvalueof{/tikz/circuitikz/tripoles/american xor port/port width}\pgf@circ@res@right
    \pgfpathmoveto{\pgfpoint{\pgf@circ@res@right}{0pt}}
    \pgfpathlineto{\pgfpoint{\pgf@circ@res@other}{0pt}}

    \pgfusepath{draw}

  \pgfsetlinewidth{2\pgflinewidth}

  \edef\pgf@circ@math@angle{\pgfkeysvalueof{/tikz/circuitikz/tripoles/american xor port/angle}}%

  \pgfpathmoveto{\pgfpoint{\pgf@circ@res@other}{0pt}}% for symmetry
  \pgfpatharc{0}{90}{2\pgf@circ@res@other and \pgf@circ@res@up}%
  \pgfpatharc{\pgf@circ@math@angle}{-\pgf@circ@math@angle}{\pgf@circ@math@xradius and \pgf@circ@math@yradius}%
  \pgfpatharc{-90}{0}{2\pgf@circ@res@other and \pgf@circ@res@up}%
  \pgfpathclose

  \pgfmathsetlength{\pgf@circ@res@temp}{(\pgf@circ@math@yradiusA)*sin(\pgf@circ@math@angle)}%

  \pgfpathmoveto{\pgfpoint{-\pgf@circ@res@other-\pgf@circ@math@distance}{\pgf@circ@res@temp}}% first arc
  \pgfpatharc{\pgf@circ@math@angle}{-\pgf@circ@math@angle}{\pgf@circ@math@xradiusA and \pgf@circ@math@yradiusA}%

    \pgfusepath{draw}
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% xnor %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\pgfcircdeclarelogicport{xnor}{
  \pgfkeysgetvalue{/tikz/circuitikz/tripoles/american xnor port/angle}{\pgf@circ@math@angle}%
  \pgf@circ@res@other=\pgfkeysvalueof{/tikz/circuitikz/tripoles/american xnor port/inner}\pgf@circ@res@right
  \pgfmathsetlengthmacro{\pgf@circ@math@xradius}{\pgf@circ@res@other /(1 - cos(\pgf@circ@math@angle)}%
  \pgfmathsetlengthmacro{\pgf@circ@math@yradius}{\pgf@circ@res@up / sin(\pgf@circ@math@angle))}%
  \pgf@circ@res@other=\pgfkeysvalueof{/tikz/circuitikz/tripoles/american xnor port/port width}\pgf@circ@res@right
  \pgfmathsetlengthmacro{\pgf@circ@math@xorigin}{\pgf@circ@res@other + \pgf@circ@math@xradius*cos(\pgf@circ@math@angle)}%
  \pgf@circ@res@temp=\pgfkeysvalueof{/tikz/circuitikz/tripoles/american xor port/distance}\pgf@circ@res@right
  \pgfmathsetlengthmacro{\pgf@circ@math@distance}{\pgf@circ@res@temp}
% this compensates for the effect of the line width on the gap between the arcs
  \pgfmathsetlengthmacro{\pgf@circ@math@yradiusA}{\pgf@circ@math@yradius -2\pgflinewidth}%
  \pgfmathsetlengthmacro{\pgf@circ@math@xradiusA}{\pgf@circ@math@xradius -2\pgflinewidth}%

    \pgfextracty{\pgf@circ@res@temp}{\step}%
  \pgf@circ@res@step = \dimexpr 2\pgf@circ@res@temp -2\pgf@circ@res@up\relax
  \pgf@circ@res@count = \inputs\relax
  \loop\ifnum\pgf@circ@res@count>0
    \advance\pgf@circ@res@temp by -\pgf@circ@res@step
      \pgfpathmoveto{\pgfpoint{\pgf@circ@res@left}{\pgf@circ@res@temp}}%
    \pgfmathsetmacro{\pgf@circ@math@angle}{asin(\pgf@circ@res@temp  / \pgf@circ@math@yradiusA)}%
    \pgfmathsetlength{\pgf@circ@res@other}{\pgf@circ@math@xradiusA*cos(\pgf@circ@math@angle)-\pgf@circ@math@xorigin}%
    \advance\pgf@circ@res@other by -\pgf@circ@math@distance
    \pgfpathlineto{\pgfpoint{\pgf@circ@res@other}{\pgf@circ@res@temp}}%
    \advance\pgf@circ@res@count by -1
  \repeat

    \pgf@circ@res@other=\pgfkeysvalueof{/tikz/circuitikz/tripoles/american xnor port/port width}\pgf@circ@res@right
    \pgfpathmoveto{\pgfpoint{\pgf@circ@res@right}{0pt}}
    \pgfpathlineto{\pgfpoint{\pgf@circ@res@other}{0pt}}

    \pgfusepath{draw}

  \pgfsetlinewidth{2\pgflinewidth}

  \edef\pgf@circ@math@angle{\pgfkeysvalueof{/tikz/circuitikz/tripoles/american xnor port/angle}}%
  \pgf@circ@res@step = \pgfkeysvalueof{/tikz/circuitikz/tripoles/american xnor port/circle width}\pgf@circ@res@right
  \pgf@circ@res@temp = \dimexpr 2\pgf@circ@res@other - \pgf@circ@res@step\relax
  \advance\pgf@circ@res@other by -\pgf@circ@res@step

  \pgfpathmoveto{\pgfpoint{\pgf@circ@res@other}{0pt}}% for symmetry
  \pgfpatharc{0}{90}{\pgf@circ@res@temp and \pgf@circ@res@up}%
  \pgfpatharc{\pgf@circ@math@angle}{-\pgf@circ@math@angle}{\pgf@circ@math@xradius and \pgf@circ@math@yradius}%
  \pgfpatharc{-90}{0}{\pgf@circ@res@temp and \pgf@circ@res@up}%
  \pgfpathclose

    \pgfpathellipse
        {\pgfpoint{\pgf@circ@res@other+.5\pgf@circ@res@step}{0pt}}
        {\pgfpoint{.5\pgf@circ@res@step}{0pt}}
        {\pgfpoint{0pt}{.5\pgf@circ@res@step}}

  \pgf@circ@res@other=\pgfkeysvalueof{/tikz/circuitikz/tripoles/american xnor port/port width}\pgf@circ@res@left
  \pgfmathsetlength{\pgf@circ@res@temp}{(\pgf@circ@math@yradiusA)*sin(\pgf@circ@math@angle)}%

  \pgfpathmoveto{\pgfpoint{\pgf@circ@res@other-\pgf@circ@math@distance}{\pgf@circ@res@temp}}% first arc
  \pgfpatharc{\pgf@circ@math@angle}{-\pgf@circ@math@angle}{\pgf@circ@math@xradiusA and \pgf@circ@math@yradiusA}%

    \pgfusepath{draw}
}
\makeatother
\begin{document}
\begin{circuitikz}
\node[american and port] at (0,0) {};
\node[american nand port,number inputs=3] at (0,-2) {};
\node[american or port,number inputs=4] at (2,0) {};
\node[american nor port,number inputs=5] at (2,-2) {};
\node[american xor port,number inputs=6] at (4,0) {};
\node[american xnor port,number inputs=7] at (4,-2) {};
\end{circuitikz}
\end{document}

demo

John Kormylo
  • 79,712
  • 3
  • 50
  • 120
  • I hope that your solution some day will be included into package :) – Zarko Jun 03 '17 at 00:48
  • Do you have a similar code for the European ports at hand? – TeXnician Sep 12 '18 at 10:38
  • @TeXnician - No, but it would not be too difficult. They are all just boxes with different symbols inside.. – John Kormylo Sep 12 '18 at 14:32
  • @JohnKormylo Not too difficult is always a good answer. I tried my best to port your solution, see the new answer (is kind of completely different because European ports work differently). – TeXnician Sep 12 '18 at 15:27
  • @TeXnician - I've been working on it, but keep getting an error I cannot track down, even by deleting sections of code. – John Kormylo Sep 12 '18 at 16:55
  • @JohnKormylo If it's an error about some undefined pgf math command please note that there is no port width, but only reserved for European nodes. – TeXnician Sep 12 '18 at 16:57
  • Yup,. that was the problem. – John Kormylo Sep 12 '18 at 17:46
  • FYI, I think I am almost ready (after minor changes) to include it in circuitikz now. See https://github.com/circuitikz/circuitikz/pull/158 – Rmano Feb 23 '19 at 18:47
4

Here is my version of the European gates. Due to size, I am entering this as a separate answer. There is some duplication with the American answer: \pgf@circ@res@count, \pgf@circ@logicport@input and the pgfkey /tikz/number inputs.

\documentclass{standalone}
\tracingmacros=1
\usepackage{circuitikz}

\ctikzset{tripoles/european and port/origin/.initial=0.8}
\ctikzset{tripoles/european and port/inputs/.initial=2}

\ctikzset{tripoles/european nand port/origin/.initial=0.8}
\ctikzset{tripoles/european nand port/inputs/.initial=2}

\ctikzset{tripoles/european or port/origin/.initial=0.8}
\ctikzset{tripoles/european or port/inputs/.initial=2}

\ctikzset{tripoles/european nor port/origin/.initial=0.8}
\ctikzset{tripoles/european nor port/inputs/.initial=2}

\ctikzset{tripoles/european xor port/origin/.initial=0.8}
\ctikzset{tripoles/european xor port/inputs/.initial=2}

\ctikzset{tripoles/european xnor port/origin/.initial=0.8}
\ctikzset{tripoles/european xnor port/inputs/.initial=2}

\ctikzset{tripoles/european not port/origin/.initial=0.8}
\ctikzset{tripoles/european not port/inputs/.initial=1}

\pgfkeys{/tikz/number inputs/.initial=0}
\pgfkeys{/tikz/number inputs/.default=0}

\makeatletter
\newcount{\pgf@circ@res@count}% reserve global register

\newcommand{\pgf@circ@logicport@input}[1]% #1 = \pgfmathcounter
{%
  \pgfextracty{\pgf@circ@res@up}{\northeast}%
  \step
  \pgf@circ@res@step=\dimexpr 2\pgf@y -2\pgf@circ@res@up\relax
  \advance\pgf@y by -#1\pgf@circ@res@step\relax
}%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% #1 - name
% #2 - text inside
% #3 - number of inputs
% #4 = is it a not?

\long\def\pgfcircdeclareeurologicport#1#2#3#4{
    \pgfdeclareshape{european #1 port}
    {
    \savedmacro\resize{% automatic
      \pgf@circ@res@up = \pgfkeysvalueof{/tikz/circuitikz/tripoles/european #1 port/height}\pgf@circ@Rlen
      \pgf@circ@res@up = .5\pgf@circ@res@up
      \pgf@circ@res@down = -\pgf@circ@res@up
      \pgf@circ@res@right = \pgfkeysvalueof{/tikz/circuitikz/tripoles/european #1 port/width}\pgf@circ@Rlen
      \pgf@circ@res@right = .5\pgf@circ@res@right
      \pgf@circ@res@left = -\pgf@circ@res@right
    }%
    \savedmacro\inputs{% get number of inputs
      \pgf@circ@res@count=\pgfkeysvalueof{/tikz/number inputs}\relax%
      \ifnum\pgf@circ@res@count=0
        \pgf@circ@res@count=\pgfkeysvalueof{/tikz/circuitikz/tripoles/european #1 port/inputs}\relax%
      \fi
      \ifnum\pgf@circ@res@count<2 \pgf@circ@res@count=2\fi
      \ifnum\pgf@circ@res@count>16 \pgf@circ@res@count=16\fi
      \def\inputs{\the\pgf@circ@res@count}%
    }%
    \savedanchor\step{% 1/2 gap at edges
      \pgf@circ@res@step = \pgfkeysvalueof{/tikz/circuitikz/tripoles/european #1 port/height}\pgf@circ@Rlen
      \divide\pgf@circ@res@step by #3
      \pgfpoint{\pgf@circ@res@left}{\dimexpr\pgf@circ@res@up+0.5\pgf@circ@res@step}%
    }%
    \savedanchor\northeast{\pgfpoint{\pgf@circ@res@right}{\pgf@circ@res@up}}%
    \savedanchor\southwest{\pgfpoint{\pgf@circ@res@left}{\pgf@circ@res@down}}%
    \savedanchor\left{\pgfpoint{\pgfkeysvalueof{/tikz/circuitikz/tripoles/european #1 port/reserved}\pgf@circ@res@left}{0pt}}%
    \savedanchor\right{\pgfpoint{\pgfkeysvalueof{/tikz/circuitikz/tripoles/european #1 port/reserved}\pgf@circ@res@right}{0pt}}%
    \savedanchor\origin{\pgfpoint{\pgfkeysvalueof{/tikz/circuitikz/tripoles/european #1 port/origin}\pgf@circ@res@right}{0pt}}%

    \anchor{center}{\origin}% for backwards compatibility
    % the text anchor overlaps the logic symbol
    \anchor{text}{\pgfpoint{-.5\wd\pgfnodeparttextbox}{\dimexpr.5\dp\pgfnodeparttextbox-.5\ht\pgfnodeparttextbox}}%
    % create input anchors
    \ifnum#3=1\relax
      \anchor{in}{\pgfpoint{\pgf@circ@res@left}{0pt}}% or \step
    \else 
      \expandafter\pgfutil@g@addto@macro\csname pgf@sh@s@european #1 port\endcsname{%
      \pgfmathloop%
        \ifnum\pgfmathcounter>#3%
        \else%
          %\pgfutil@ifundefined{pgf@anchor@european #1 port@in \pgfmathcounter}{% redundant
            \expandafter\xdef\csname pgf@anchor@european #1 port@in \pgfmathcounter\endcsname{%
              \noexpand\pgf@circ@logicport@input{\pgfmathcounter}% defined above
            }%
          %}{}%
        \repeatpgfmathloop%
      }
    \fi
    \anchor{out}{\pgfpoint{\pgf@circ@res@right}{0pt}}

    \anchor{left}{\left}% edges of component minus leads
    \anchor{right}{\right}

    \anchor{north east}{\northeast}% see \Compass macro
    \anchor{south west}{\southwest}
    \anchor{north}{\pgfextracty{\pgf@circ@res@up}{\northeast}%
      \pgfpoint{0cm}{\pgf@circ@res@up}}
    \anchor{north west}{\pgfextracty{\pgf@circ@res@up}{\northeast}%
      \pgfextractx{\pgf@circ@res@left}{\southwest}%
      \pgfpoint{\pgf@circ@res@left}{\pgf@circ@res@up}}
    \anchor{west}{\pgfextractx{\pgf@circ@res@left}{\sosuthwest}%
      \pgfpoint{\pgf@circ@res@left}{0cm}}
    \anchor{south}{\pgfextracty{\pgf@circ@res@down}{\southwest}%
      \pgfpoint{0cm}{\pgf@circ@res@down}}
    \anchor{south east}{\pgfextracty{\pgf@circ@res@down}{\southwest}%
      \pgfextractx{\pgf@circ@res@right}{\northeast}%
      \pgfpoint{\pgf@circ@res@right}{\pgf@circ@res@down}}
    \anchor{east}{\pgfextractx{\pgf@circ@res@right}{\northeast}%
      \pgfpoint{\pgf@circ@res@right}{0cm}}

      \backgroundpath{          
            \pgfsetcolor{\pgfkeysvalueof{/tikz/circuitikz/color}}   
            \ifnum#3=1\relax
        \pgfpathmoveto{\pgfpoint{\pgf@circ@res@left}{0pt}}%
        \pgfpathlineto{\pgfpoint{\pgfkeysvalueof{/tikz/circuitikz/tripoles/european #1 port/reserved}\pgf@circ@res@left}{0pt}}%
      \else
        \pgfextracty{\pgf@circ@res@temp}{\step}%
        \pgf@circ@res@step = \dimexpr 2\pgf@circ@res@temp -2\pgf@circ@res@up\relax
        %\pgf@circ@res@count = #3\relax% redundant
        \loop\ifnum\pgf@circ@res@count>0
          \advance\pgf@circ@res@temp by -\pgf@circ@res@step
            \pgfpathmoveto{\pgfpoint{\pgf@circ@res@left}{\pgf@circ@res@temp}}%
          \pgfpathlineto{\pgfpoint
              {\pgfkeysvalueof{/tikz/circuitikz/tripoles/european #1 port/reserved}\pgf@circ@res@left}
              {\pgf@circ@res@temp}}
          \advance\pgf@circ@res@count by -1
        \repeat
            \fi
            %
            \pgfpathmoveto{\pgfpoint{\pgf@circ@res@right}{0pt}}
            \pgfpathlineto{%
                \pgfpoint{\pgfkeysvalueof{/tikz/circuitikz/tripoles/european #1 port/reserved}\pgf@circ@res@right}{0pt}}
            %
            \edef\pgf@temp{not}
            \edef\pgf@circ@temp{#4}
            \ifx\pgf@temp\pgf@circ@temp % is a not
                \pgfpathmoveto{\pgfpoint{\pgfkeysvalueof{/tikz/circuitikz/tripoles/european #1 port/not width}\pgf@circ@res@right}{0pt}}
                \pgfpathlineto{\pgfpoint{\pgfkeysvalueof{/tikz/circuitikz/tripoles/european #1 port/reserved}\pgf@circ@res@right}%
          {\pgfkeysvalueof{/tikz/circuitikz/tripoles/european #1 port/not height}\pgf@circ@res@up}}
            \fi
            %
            \pgfusepath{draw}
            %
            \pgfpathmoveto{\pgfpointorigin}
            \pgftext{#2}
            %
            \pgfsetlinewidth{2\pgflinewidth}
            \pgfpathrectanglecorners
                {\pgfpoint{\pgfkeysvalueof{/tikz/circuitikz/tripoles/european #1 port/reserved}\pgf@circ@res@left}{\pgf@circ@res@up}}
                {\pgfpoint{\pgfkeysvalueof{/tikz/circuitikz/tripoles/european #1 port/reserved}\pgf@circ@res@right}{\pgf@circ@res@down}}
            \pgfusepath{draw}
%
%
      }
    }
}
\pgfcircdeclareeurologicport{and}{$\&$}{\pgf@circ@res@count}{}
\pgfcircdeclareeurologicport{or}{$\ge 1$}{\pgf@circ@res@count}{}
\pgfcircdeclareeurologicport{xor}{$=1$}{\pgf@circ@res@count}{}
\pgfcircdeclareeurologicport{not}{$1$}{1}{not}
\pgfcircdeclareeurologicport{nand}{$\&$}{\pgf@circ@res@count}{not}
\pgfcircdeclareeurologicport{nor}{$\ge 1$}{\pgf@circ@res@count}{not}
\pgfcircdeclareeurologicport{xnor}{$=1$}{\pgf@circ@res@count}{not}
\makeatother

\begin{document}
\begin{circuitikz}
\node[european and port] (A) at (0,0) {};
\node[european nand port,number inputs=3] at (0,-2) {};
\node[european or port,number inputs=4] at (2,0) {};
\node[european nor port,number inputs=5] at (2,-2) {};
\node[european xor port,number inputs=6] at (4,0) {};
\node[european xnor port,number inputs=7] at (4,-2) {};
\node[european not port] (B) at (0,-4) {};
\draw[red] (A.center) -- (B.center);

\end{circuitikz}
\end{document}

demo

John Kormylo
  • 79,712
  • 3
  • 50
  • 120
  • This is great (+1). Maybe you should suggest the author to include this code in the package (at https://github.com/circuitikz/circuitikz/issues I guess). If you don't want to do this, but would agree to I could open an issue. – TeXnician Sep 12 '18 at 19:38
  • Of course, they would no longer be tripoles. – John Kormylo Sep 13 '18 at 02:07
  • That's probably something the developer should decide. I have opened an issue at https://github.com/circuitikz/circuitikz/issues/105. – TeXnician Sep 13 '18 at 07:43
  • @TeXnician John Kormylo I am trying to collect all the enhancement and doing pull requests through my fork... would you mind if I add your code? I would need an "A U Thor author@example.com attribution for the patch... – Rmano Nov 04 '18 at 08:07
  • @Rmano You do not need to ask me, because John Kormylo's code is much better ;) – TeXnician Nov 04 '18 at 10:37
  • @TeXnician ...yep, I am asking both of you... – Rmano Nov 04 '18 at 19:01
  • Fine with me. I assume this site doesn't claim copyrights, otherwise they would need a disclaimer every time you submit an answer. – John Kormylo Nov 04 '18 at 21:45
  • @JohnKormylo --- thanks for the availability. I have a little problem merging the code, if you have a bit of time, could you have a look at https://github.com/circuitikz/circuitikz/issues/105 ? Thanks! – Rmano Feb 21 '19 at 13:45
  • @Rmano - Visited the site. The backward compatibility problems seem to deal with inheritance. I have always regarded inheritance as a bad idea and try to avoid it. Tell me what anchors need to be added and I will add them. – John Kormylo Feb 21 '19 at 16:06
  • @JohnKormylo the problem is that the shape and port is switched by inheritance to american and port or european and port following a global option; and the problem is that I do not know how to do that avoiding inheritance... all the anchors are there, but they do not go from the specific american and port to the generic and port. If there is another method of creating the alias, it would be great. – Rmano Feb 21 '19 at 16:18
  • Yes, I know... but I really would like to implement your nice ports in a backward compatible way into circuitikz. Will work a bit on it during the weekend, thanks for the hints!. – Rmano Feb 21 '19 at 16:39
  • @Rmano - Since I first gave that answer, circuitikz changed its basic approach, using \pgfcircdeclarelogicport to generate all ports. The first step would be to throw all of that out and do it the old way. If you then want to try to consolidate all the ports into one (slower but smaller) macro, you should start from scratch. – John Kormylo Feb 21 '19 at 16:53
  • No --- your ports really do work, and the approach didn't changed a lot. It's just the aliasing of the shapes (american and european) that throws everything off. I'll try to see if I can solve it. I identified the piece of code that fails (it's the inherit part), I'll work on it. @TeXnician --- ¿do you have any idea on how to solve it? – Rmano Feb 21 '19 at 17:02
  • 1
    @Rmano I'll try to look at it over the weekend. I'll respond to your comment on GitHub then. – TeXnician Feb 21 '19 at 17:48
  • Thanks a lot for the code, but the anchors seem screwed. The out anchor is in the center, and the center anchor is on the port's output (but not on the terminal wire where out should be). The latter is apparent in the picture posted in your answer. – ScumCoder Feb 24 '19 at 13:09
  • Nevermind, I just copypasted the definition of the east anchor (which is exactly where out should be), and corrected a typo in the definition of center (there shouldn't be a \pgf@circ@res@right there). – ScumCoder Feb 24 '19 at 14:01
  • @ScumCoder - So did you put the center anchor in the center (where it belongs) or to the right (for backward compatibility)? See https://tex.stackexchange.com/questions/372462/circuitikz-logic-port-design?r=SearchResults&s=1|65.7986 – John Kormylo Feb 24 '19 at 18:01
  • @JohnKormylo Oh, OK, so the center anchor was actually correct. (I didn't know that this strange behavior is normal because I never used this anchor before). – ScumCoder Feb 24 '19 at 20:54
  • On a side note, the in anchor of the not port is also screwed. The definition should have an additional \pgfextractx{\pgf@circ@res@left}{\southwest} to refresh the left variable. – ScumCoder Feb 24 '19 at 20:55
2

Just for those who are interested in the European ports, here is an adaption of the American ports created by John Kormylo (I hope I did not mess it up completely).

european ports

\documentclass{standalone}
\usepackage{circuitikz}

\ctikzset{tripoles/european and port/origin/.initial=0.8}
\ctikzset{tripoles/european and port/inputs/.initial=2}

\ctikzset{tripoles/european nand port/origin/.initial=0.8}
\ctikzset{tripoles/european nand port/inputs/.initial=2}

\ctikzset{tripoles/european nor port/origin/.initial=0.8}
\ctikzset{tripoles/european nor port/inputs/.initial=2}

\ctikzset{tripoles/european or port/origin/.initial=0.8}
\ctikzset{tripoles/european or port/inputs/.initial=2}

\ctikzset{tripoles/european xor port/origin/.initial=0.8}
\ctikzset{tripoles/european xor port/inputs/.initial=2}

\ctikzset{tripoles/european xnor port/origin/.initial=0.8}
\ctikzset{tripoles/european xnor port/inputs/.initial=2}

\pgfkeys{/tikz/number inputs/.initial=0}
\pgfkeys{/tikz/number inputs/.default=0}

\makeatletter
\newcount{\pgf@circ@res@count}% reserve global register
\newcommand{\pgf@circ@logicport@input}[1]% #1 = \pgfmathcounter
{%
  \pgfextracty{\pgf@circ@res@up}{\northeast}%
  \step
  \pgf@circ@res@step=\dimexpr 2\pgf@y -2\pgf@circ@res@up\relax
  \advance\pgf@y by -#1\pgf@circ@res@step\relax
}

\long\def\pgfcircdeclareeurologicport#1#2#3#4{
    \pgfdeclareshape{european #1 port}
    {
    \savedmacro\resize{% automatic
      \pgf@circ@res@up = \pgfkeysvalueof{/tikz/circuitikz/tripoles/european #1 port/height}\pgf@circ@Rlen
      \pgf@circ@res@up = .5\pgf@circ@res@up
      \pgf@circ@res@down = -\pgf@circ@res@up
      \pgf@circ@res@right = \pgfkeysvalueof{/tikz/circuitikz/tripoles/european #1 port/width}\pgf@circ@Rlen
      \pgf@circ@res@right = .5\pgf@circ@res@right
      \pgf@circ@res@left = -\pgf@circ@res@right
    }%
    \savedmacro\inputs{% get number of inputs
      \pgf@circ@res@count=\pgfkeysvalueof{/tikz/number inputs}\relax%
      \ifnum\pgf@circ@res@count=0
        \pgf@circ@res@count=\pgfkeysvalueof{/tikz/circuitikz/tripoles/european #1 port/inputs}\relax%
      \fi
      \ifnum\pgf@circ@res@count<2 \pgf@circ@res@count=2\fi
      \ifnum\pgf@circ@res@count>16 \pgf@circ@res@count=16\fi
      \def\inputs{\the\pgf@circ@res@count}%
    }%
    \savedanchor\step{% 1/2 gap at edges
      \pgf@circ@res@step = \pgfkeysvalueof{/tikz/circuitikz/tripoles/european #1 port/height}\pgf@circ@Rlen
      \divide\pgf@circ@res@step by \pgf@circ@res@count
      \pgfpoint{\pgf@circ@res@left}{\dimexpr\pgf@circ@res@up+0.5\pgf@circ@res@step}%
    }%
    \savedanchor\northwest{%
      \pgf@y=\pgfkeysvalueof{/tikz/circuitikz/tripoles/european #1 port/height}\pgf@circ@Rlen
      \pgf@y=.5\pgf@y
      \pgf@x=-\pgfkeysvalueof{/tikz/circuitikz/tripoles/european #1 port/width}\pgf@circ@Rlen
      \pgf@x=.5\pgf@x
    } 
    \savedanchor\northeast{\pgfpoint{\pgf@circ@res@right}{\pgf@circ@res@up}}
    \savedanchor\southwest{\pgfpoint{\pgf@circ@res@left}{\pgf@circ@res@down}}
    \savedanchor\left{\pgfpoint{\pgfkeysvalueof{/tikz/circuitikz/tripoles/european #1 port/reserved}\pgf@circ@res@left}{0pt}}
    \savedanchor\right{\pgfpoint{\pgfkeysvalueof{/tikz/circuitikz/tripoles/european #1 port/reserved}\pgf@circ@res@right}{0pt}}
    \savedanchor\origin{\pgfpoint{\pgfkeysvalueof{/tikz/circuitikz/tripoles/european #1 port/origin}\pgf@circ@res@right}{0pt}}
      %
    \anchor{center}{\origin}% for backwards compatibility
    \anchor{text}{\pgfpoint{-.5\wd\pgfnodeparttextbox}{\dimexpr.5\dp\pgfnodeparttextbox-.5\ht\pgfnodeparttextbox}}
        %
      \expandafter\pgfutil@g@addto@macro\csname pgf@sh@s@european #1 port\endcsname{%
      \pgfmathloop%
      \ifnum\pgfmathcounter>\pgf@circ@res@count%
      \else%
        %\pgfutil@ifundefined{pgf@anchor@american #1 port@in \pgfmathcounter}{%
          \expandafter\xdef\csname pgf@anchor@european #1 port@in \pgfmathcounter\endcsname{%
            \noexpand\pgf@circ@logicport@input{\pgfmathcounter}% defined above
          }%
        %}{}%
      \repeatpgfmathloop%
    }
    %
    \anchor{out}{\pgfpoint{\pgf@circ@res@right}{0pt}}
        %
    \anchor{left}{\left}% edges of component mius leads
    \anchor{right}{\right}
        %
    \anchor{north east}{\northeast}% see \Compass macro
    \anchor{south west}{\southwest}
    \anchor{north}{\pgfextracty{\pgf@circ@res@up}{\northeast}%
      \pgfpoint{0cm}{\pgf@circ@res@up}}
    \anchor{north west}{\pgfextracty{\pgf@circ@res@up}{\northeast}%
      \pgfextractx{\pgf@circ@res@left}{\southwest}%
      \pgfpoint{\pgf@circ@res@left}{\pgf@circ@res@up}}
    \anchor{west}{\pgfextractx{\pgf@circ@res@left}{\sosuthwest}%
      \pgfpoint{\pgf@circ@res@left}{0cm}}
    \anchor{south}{\pgfextracty{\pgf@circ@res@down}{\southwest}%
      \pgfpoint{0cm}{\pgf@circ@res@down}}
    \anchor{south east}{\pgfextracty{\pgf@circ@res@down}{\southwest}%
      \pgfextractx{\pgf@circ@res@right}{\northeast}%
      \pgfpoint{\pgf@circ@res@right}{\pgf@circ@res@down}}
    \anchor{east}{\pgfextractx{\pgf@circ@res@right}{\northeast}%
      \pgfpoint{\pgf@circ@res@right}{0cm}}
      \backgroundpath{          
            \pgfsetcolor{\pgfkeysvalueof{/tikz/circuitikz/color}}   
            \northwest
            \pgf@circ@res@up = \pgf@y 
            \pgf@circ@res@down = -\pgf@y
            \pgf@circ@res@right = -\pgf@x
            \pgf@circ@res@left = \pgf@x
            \def\pgf@temp{1}
            \def\pgf@circ@temp{#3}
            \pgfextracty{\pgf@circ@res@temp}{\step}%
          \pgf@circ@res@step = \dimexpr 2\pgf@circ@res@temp -2\pgf@circ@res@up\relax
          \pgf@circ@res@count = \inputs\relax
          \loop\ifnum\pgf@circ@res@count>0
            \advance\pgf@circ@res@temp by -\pgf@circ@res@step
          \pgfpathmoveto{\pgfpoint{\pgf@circ@res@left}{\pgf@circ@res@temp}}%
            \pgfpathlineto{\pgfpoint
                {\pgfkeysvalueof{/tikz/circuitikz/tripoles/european #1 port/reserved}\pgf@circ@res@left}
              {\pgf@circ@res@temp}}
            \advance\pgf@circ@res@count by -1
          \repeat
            %
            \pgfpathmoveto{\pgfpoint{\pgf@circ@res@right}{0pt}}
            \pgfpathlineto{
                \pgfpoint{\pgfkeysvalueof{/tikz/circuitikz/tripoles/european #1 port/reserved}\pgf@circ@res@right}{0pt}}
            %
            \edef\pgf@temp{not}
            \edef\pgf@circ@temp{#4}
            \ifx\pgf@temp\pgf@circ@temp % is a not
                \pgfpathmoveto{\pgfpoint{\pgfkeysvalueof{/tikz/circuitikz/tripoles/european #1 port/not width}\pgf@circ@res@right}{0pt}}
                \pgfpathlineto{\pgfpoint{\pgfkeysvalueof{/tikz/circuitikz/tripoles/european #1 port/reserved}\pgf@circ@res@right}{\pgfkeysvalueof{/tikz/circuitikz/tripoles/european #1 port/not height}\pgf@circ@res@up}}
            \fi
            %
            \pgfusepath{draw}
            %
            \pgfpathmoveto{\pgfpointorigin}
            \pgftext{#2}
            %
            \pgfsetlinewidth{2\pgflinewidth}
            \pgfpathrectanglecorners
                {\pgfpoint{\pgfkeysvalueof{/tikz/circuitikz/tripoles/european #1 port/reserved}\pgf@circ@res@left}{\pgf@circ@res@up}}
                {\pgfpoint{\pgfkeysvalueof{/tikz/circuitikz/tripoles/european #1 port/reserved}\pgf@circ@res@right}{\pgf@circ@res@down}}
            \pgfusepath{draw}
      }
    }
}

\pgfcircdeclareeurologicport{and}{$\&$}{2}{}
\pgfcircdeclareeurologicport{or}{$\ge 1$}{2}{}
\pgfcircdeclareeurologicport{xor}{$=1$}{2}{}
\pgfcircdeclareeurologicport{not}{$1$}{1}{not}
\pgfcircdeclareeurologicport{nand}{$\&$}{2}{not}
\pgfcircdeclareeurologicport{nor}{$\ge 1$}{2}{not}
\pgfcircdeclareeurologicport{xnor}{$=1$}{2}{not}
\makeatother
\begin{document}
\begin{circuitikz}
\node[european and port] at (0,0) {};
\node[european nand port,number inputs=3] at (0,-2) {};
\node[european or port,number inputs=4] at (2,0) {};
\node[european nor port,number inputs=5] at (2,-2) {};
\node[european xor port,number inputs=6] at (4,0) {};
\node[european xnor port,number inputs=7] at (4,-2) {};
\end{circuitikz}
\end{document}
TeXnician
  • 33,589