tikz.dev / TikZpingus Manual

The TikZpingus package

Internals

C.10 Extras

Everything else you can put on a penguin is an extra. An extra consists of some keys, a switch \if@pingu@x@<name>@ and the code to draw. \pingu@create@extra creates all of it: it takes the name, the keys (which call \pingu@set@extra to switch the extra on) and the defaults, which are appended to /pingu/extra defaults so that every penguin starts with a clean set. Extras behind the body are drawn by \pingu@draw@eb@<name> and extras in front of it by \pingu@draw@ea@<name>. The lists with the order of the extras (implementation (lines 1467–1576) and implementation (lines 1580–1674)) decide what covers what, a later extra is drawn above an earlier one. They are the only place to change the order of two extras, and a new extra has to be added to one of them. The face (glasses, mask, …) is in front of the headphones, which are behind the hats, and the pants are behind the belt. This is the cup, an extra below the head:

\pingu@create@extra{cup}{%
cup/.code = {\pingu@set@extra{cup}{true}\pingu@color{cup}{#1}},
cup/.default = pingu@green,
cup steam/.code = \pingu@color{cup@steam}{#1},%
cup steam/.default = lightgray!90!orange,%
cup steam shift/.code = \def\pingu@x@cup@steam@shift{#1},%
cup steam opacity/.code = \def\pingu@x@cup@steam@opacity{#1},%
cup straw/.code = \pingu@color{cup@straw}{#1}%
}{cup straw=\pingu@color@cup,cup steam=\@pingu@none,cup steam shift=0mm,cup steam opacity=.55}

\def\pingu@draw@eb@cup{%
\pingu@block[rounded corners=.25mm]{\pingu@color@cup} (\pingu@name-belly-center)++(-.325cm,.275cm) to[bend right=2] ++(.5mm,-.675cm) to[bend right=8] ++(.55cm,\z@) to[bend right=2] ++(.5mm,.675cm);
\path (\pingu@name-belly-center)++(0,.275cm) -- (\pingu@name-bill) coordinate[pos=.5,xshift=-2mm] (\pingu@name-cup-straw-outer-angle);
\path (\pingu@name-belly-center)++(-.115cm,.275cm) coordinate (\pingu@name-straw-outer-start);
\pingu@block[rounded corners=.15mm]{\pingu@color@cup@straw} (\pingu@name-straw-outer-start) -- (\pingu@name-cup-straw-outer-angle) -- (\pingu@name-bill) -- ++(.5mm,0) -- ([xshift=.5mm]\pingu@name-cup-straw-outer-angle) -- ([xshift=.5mm]\pingu@name-straw-outer-start) -- cycle;
\pingu@block{\pingu@color@cup} (\pingu@name-belly-center)++(0,.275cm) ellipse [x radius=.325cm,y radius=.5mm];

\pgfonlayer{\pingu@L@foreground}
\pingu@block[rounded corners=.05mm,opacity=\pingu@x@cup@steam@opacity]{\pingu@color@cup@steam} (\pingu@name-belly-center)++(1.5mm+\pingu@x@cup@steam@shift,4mm) coordinate(@) to[out=100,in=260] ++(.3mm,3.75mm) -- ++(.1mm,0) to[out=280,in=80] ([xshift=.1mm]@) -- cycle;
\pingu@block[rounded corners=.05mm,opacity=\pingu@x@cup@steam@opacity]{\pingu@color@cup@steam} (\pingu@name-belly-center)++(0mm+\pingu@x@cup@steam@shift,3.33mm) coordinate(@) to[out=100,in=260] ++(.2mm,2.75mm) -- ++(.1mm,0) to[out=280,in=80] ([xshift=.1mm]@) -- cycle;
\pingu@block[rounded corners=.05mm,opacity=\pingu@x@cup@steam@opacity]{\pingu@color@cup@steam} (\pingu@name-belly-center)++(-1.25mm++\pingu@x@cup@steam@shift,3.65mm) coordinate(@) to[out=100,in=260] ++(.3mm,3.75mm) -- ++(.1mm,0) to[out=280,in=80] ([xshift=.1mm]@) -- cycle;
\endpgfonlayer
}

And the halo above the head, which uses a layer for the glow:

\newif\if@pingu@x@halo@glow
\newif\if@pingu@x@halo@above
\pingu@create@extra{halo}{%
halo/.code = \pingu@set@extra{halo}{true}\pingu@color{halo}{#1},
halo/.default = pingu@lightblue,
halo raise/.code = \def\pingu@x@halo@raise{#1},
halo above/.is if = @pingu@x@halo@above,
halo glow/.is if = @pingu@x@halo@glow% only active if glows loaded
}{halo glow=\ifpengu@setup@glows@ true\else false\fi,halo raise=0mm,halo above=false}

\def\pingu@draw@ea@halo{%
\if@pingu@x@halo@above\pingu@layer{foreground}[]\fi
\pingu@block[even odd rule]{\pingu@color@halo} ([yshift=\pingu@x@halo@raise]\pingu@name-head-top) ellipse [x radius=\pingu@w@half-\pingu@one,y radius=2.5mm] ellipse [x radius=\pingu@w@half-1.95mm,y radius=1.55mm];
\if@pingu@x@halo@glow
\pingu@block[even odd rule,/pingu/@glow]{\pingu@color@halo} ([yshift=\pingu@x@halo@raise]\pingu@name-head-top) ellipse [x radius=(\pingu@w@half-1.95mm)*1.7,y radius=1.55mm*2.35] ellipse [x radius=\pingu@w@half-1.95mm,y radius=1.55mm];
\fi
\if@pingu@x@halo@above\endpingu@layer{foreground}\fi
}

Extras for the wings are created with \pingu@create@wing@extra, which creates the keys for both wings:

\pingu@create@wing@extra{cane}{%
cane \@lr/.code = {\pingu@set@extra{cane\@lr}{true}\pingu@color{cane\@lr}{##1}},
cane \@lr/.default = pingu@bronze,
cane \@lr\space raise/.code = {\@namedef{pinug@x@cane@raise@\@lr}{##1}},
cane \@lr\space length/.code = {\@namedef{pinug@x@cane@length@\@lr}{##1}},
}{cane \@lr\space raise=0mm,cane \@lr\space length=15mm}

% #1 wing
\def\pingu@draw@wi@cane#1{%
\pingu@setup@wing{cane}{#1}%
\if@pingu@wing@item@side@left@
\pingu@block[thick,rotate around={\@angle+5:(\pingu@name-wing-#1)}]{\@col}(\pingu@name-wing-#1)++(0,-7mm+\pinug@x@cane@raise@left) -- ++(0,\csname pinug@x@cane@length@#1\endcsname) arc(180:0:2.25mm and 2.2mm) arc(360:180:.3mm and .275mm) arc(0:180:1.65mm and 1.65mm) -- ++(0,-\csname pinug@x@cane@length@#1\endcsname) arc(360:180:.3mm and .275mm) -- cycle;
\else
\pingu@block[thick,rotate around={\@angle-5:(\pingu@name-wing-#1)}]{\@col}(\pingu@name-wing-#1)++(0,-7mm+\pinug@x@cane@raise@right) -- ++(0,\csname pinug@x@cane@length@#1\endcsname) arc(0:180:2.25mm and 2.2mm) arc(180:360:.3mm and .275mm) arc(180:0:1.65mm and 1.65mm) -- ++(0,-\csname pinug@x@cane@length@#1\endcsname) arc(180:360:.3mm and .275mm) -- cycle;
\fi
}

All extras are grouped in libraries (christmas-lib, hats-lib, …) which are regions of the source, as the map in Section C.2 shows. A library is only a convenient place to look: nothing is loaded on demand.