今年のアドベントカレンダーの重点テーマは「(La)TeXで幸せになる方法」です。そもそもLaTeXは文書を作成するためのソフトウェアなので、「LaTeXで幸せになる」ための“正攻法”は「幸せな出力を得ること」になるでしょう。そして、LaTeXで手軽にできる「幸せな出力」と聞いて真っ先に思いつくものといえば、やっぱりコレでしょう。
ツイッタァー(現𝕏)のどっかの某氏🙃のアカウントを見に行けば見飽きるほど大量に豊富に貼られている「いつものゆきだるま☃画像」です(素敵😊)。
※説明の都合上、幸せと無関係な要素(🦆とか🙃とか)は除去しました。
……なのですが、ここで問題です。
この画像を実際にLaTeXで作るにはどうすればよいでしょう?
※ツイッタァー(現𝕏)に上げているのはPNG画像ですが、PDF→PNGの変換は容易であるため、ここでは元の「PDFの画像(文書)」を作ることを問題にします。
とにかくフツーの☃画像してみる話
TikZしてscsnowmanしたら完成……しない話
一見するととても簡単な話に見えます。画像の背景は単純に色を塗っただけのものです。空の部分はグラデーションになっていますが、これもTikZで簡単に実現できそうです。単一のtikzpicture環境の中身をそのまま出力文書としたいのでstandaloneクラス1を利用しましょう。
\documentclass{standalone}
\usepackage[svgnames]{xcolor}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}[x=1bp,y=1bp]
\useasboundingbox (0,0) rectangle (480,360);
\fill[DarkGreen] (0,0) rectangle (480,40);
\fill[SkyBlue!5] (0,40) rectangle (480,360);
\shade[top color=SkyBlue!65, bottom color=SkyBlue!5]
(0,180) rectangle (480,360);
\end{tikzpicture}
\end{document}
このソースをpdflatexでタイプセットすると以下の出力が得られます。
完璧ですね!😃
あとはscsnowmanパッケージを追加して適当な位置に赤マフラーの☃を配置するだけです。
\documentclass{standalone}
\usepackage[svgnames]{xcolor}
\usepackage{tikz,scsnowman}
\begin{document}
\begin{tikzpicture}[x=1bp,y=1bp]
\useasboundingbox (0,0) rectangle (480,360);
\fill[DarkGreen] (0,0) rectangle (480,40);
\fill[SkyBlue!5] (0,40) rectangle (480,360);
\shade[top color=SkyBlue!65, bottom color=SkyBlue!5]
(0,180) rectangle (480,360);
\node at (232,248) {\scsnowman[scale=64,
muffler=Red, hat=Green, buttons=RoyalBlue, arms=Brown, snow=SkyBlue]};
\end{tikzpicture}
\end{document}
これで完成……アレレ、なんか☃が青ざめているようです😰 何が起こったのでしょうか?
scsnowmanでフツーに☃できない話
実は\scsnowman
命令は既定では☃の中身を塗りつぶしません2。なので背景の空の色が見えてしまっているのです。(雪玉の中身についても同様です。)
とはいえ、\scsnowman
命令にはいっぱいオプションがあったはずなので、恐らく「体の色」の指定もきっとできるでしょう。そう思ってマニュアルを見ると、body
というオプションがあることがわかります。体の色を白にするために\scsnowman
のオプションにbody=White
を追加してみましょう。
\node at (232,248) {\scsnowman[scale=64, body=White,
muffler=Red, hat=Green, buttons=RoyalBlue, arms=Brown,
snow=SkyBlue]};
アレレ、顔がなくなってしまいました😱
この理由は、body
オプションを指定すると輪郭線の扱い3が変わるからです。具体的には「全体の輪郭線は描かれなくなりその内部の線(顔のパーツの線やマフラーの輪郭線など)は白で描かれる4」ようになります。顔のパーツと体が同じ色なので見えなくなったわけです。
※body
オプションがどういう効果をもっているかは白以外の色を指定してみればわかるでしょう。以下の画像はbody=Turquoise
を指定した結果です。
それでは、当初考えていたように「輪郭線をフツーに描いて中身を白く塗りつぶす」にはどう設定すればいいのでしょうか。実は現状のscsnowmanパッケージはこの設定をサポートしていません。フツーの☃画像を出力して幸せになるのは案外大変なようです😧
それでもフツーの☃画像したい話
というわけでここからが本題です。scsnowmanパッケージをフツーに使うだけではフツーの☃画像が作れないことがわかりました。フツーの☃画像を作って幸せになるにはどうすればいいでしょうか。ここでは3つの解決策を紹介します。
方法①:scsnowman+パッケージを使う
実はこの「色指定の自由度がチョット足りない」という問題は、3年前の「TeX & LaTeX Advent Calendar 2020」の記事で既に指摘されています。
そして、その記事の筆者により作製された「scsnowmanを拡張するパッケージ」であるscsnowman+ パッケージが公開されています。
scsnowman+ パッケージを読み込むと、\scsnowman
命令が拡張されて「*-形」である\scsnowman*
が使えるようになります。この\scsnowman*
では「体の塗りつぶしの色を指定する」ためのbodyfill
や「雪玉の塗りつぶしの色を指定する」ためのsnowfill
などの追加のオプションを指定して色をもっと自由に設定できるようになっています。
今回は体と雪玉を白く塗りつぶしたいのでbodyfill=White, snowfill=White
とオプションを指定しましょう。
\documentclass{standalone}
\usepackage[svgnames]{xcolor}
\usepackage{tikz,scsnowman+}
\begin{document}
\begin{tikzpicture}[x=1bp,y=1bp]
\useasboundingbox (0,0) rectangle (480,360);
\fill[DarkGreen] (0,0) rectangle (480,40);
\fill[SkyBlue!5] (0,40) rectangle (480,360);
\shade[top color=SkyBlue!65, bottom color=SkyBlue!5]
(0,180) rectangle (480,360);
\node at (232,248) {\scsnowman*[scale=64,
muffler=Red, hat=Green, buttons=RoyalBlue, arms=Brown, snow=SkyBlue,
bodyfill=White, snowfill=White]};
\end{tikzpicture}
\end{document}
フツーの☃画像が完成しました(幸せ😊)
方法②:scsnowman-libを使う
ところで、どっかの某氏🙃は飽きもせず延々とフツーの☃画像を流し続けているわけですから、どっかの某氏🙃も何らかの手段を持っているはずです。どっかの某氏🙃が使っている自作のライブラリscsnowman-libは以下のレポジトリで公開されています。
※他のものと一緒になっていてヤヤコシイことになっていますが、scsnowmoan-lib/
ディレクトリ以下のファイル群が該当のファイルなので、これらのファイル群を“TeXが見える場所”に配置してください。
scsnowmanパッケージでは「ユーザが自由に☃の形状を定義する」ための「ゆきだるま定義ファイル(snowman definition file)」という仕組が用意されており、scsnowman-libではその仕組を利用して標準と異なる外形の☃を実現するための様々なゆきだるま定義ファイルを提供しています。
※「ゆきだるま定義ファイル」によりscsnowmanを拡張する話は2021年のアドベントカレンダー5の記事でも登場しています。
※便宜的に以降の説明では「ゆきだるま定義ファイル」のことを“ライブラリ”と呼ぶことにします6。
今回はこの中で最も基本的な zrextra ライブラリ(ファイル名は scsnowman-zrextra.def)を利用します。このライブラリでは「標準と同じ外形だが塗りつぶしの色が別個に指定できる」という形状の☃を定義しています。
zrextra
ライブラリを読み込むにはscsnowmanパッケージの\usescsnowmanlibrary
命令を利用します。
\usepackage{scsnowman}
\usescsnowmanlibrary{zrextra}
これによりzrextra
特有の機能の設定をするための\sczrextrasetup
命令が使えるようになります7。ここでbodyfill
キーにより体の塗りつぶしの色、snowfill
キーで雪玉の塗りつぶしの色を指定します。
\sczrextrasetup{bodyfill=White,snowfill=White}
☃の出力に対してzrextra
ライブラリで定義した形状を有効にするには\scsnowman
命令のshape
キーにzrextra
を指定する必要があります。
\scsnowman[scale=64, shape=zrextra, …(他オプション)…]
以上を踏まえると、全体のソースコードは以下のようになります。
\documentclass{standalone}
\usepackage[svgnames]{xcolor}
\usepackage{tikz,scsnowman}
\usescsnowmanlibrary{zrextra}
\sczrextrasetup{bodyfill=White,snowfill=White}
\begin{document}
\begin{tikzpicture}[x=1bp,y=1bp]
\useasboundingbox (0,0) rectangle (480,360);
\fill[DarkGreen] (0,0) rectangle (480,40);
\fill[SkyBlue!5] (0,40) rectangle (480,360);
\shade[top color=SkyBlue!65, bottom color=SkyBlue!5]
(0,180) rectangle (480,360);
\node at (232,248) {\scsnowman[scale=64, shape=zrextra,
muffler=Red, hat=Green, buttons=RoyalBlue, arms=Brown, snow=SkyBlue]};
\end{tikzpicture}
\end{document}
再びフツーの☃画像が完成しました(幸せ😊)
方法③:scsnowmanだけで頑張る
いままでに紹介した2つの方法はどれも「scsnowmanパッケージとは別のもの」を使うものでした。これらのソフトウェアは別個にインストールする必要があるためソースコードの可搬性という点で問題になる可能性があります。そういうわけで、最後にscsnowmanパッケージだけでフツーの☃画像を実現する“裏技”を紹介することにします。
この記事の初めのほうで「\scsnowman
命令のbody
キーを指定したら“顔なし”になった😱」という話がありましたが、その“顔なし”の☃をもう一度見てみましょう。このままでは使いものになりませんが、この上にもう一度☃を(body
無しで)描いてみるとどうでしょう。今度は塗りつぶしがないので下の白色がそのまま残り、しかも顔のパーツや輪郭線はちゃんと描かれることになります。なんとこれで所望の☃になっています!😲
実際にこの方針を試してみましょう。まずbody=White
を指定したscsnowman
を配置します。雪玉も内部を白く塗りつぶしたいので、ここではsnow=White
を指定します(これで雪玉全体が白く塗りつぶされる)。その他のパーツはここでは描く必要がないので省略します。
\node at (232,248) {\scsnowman[scale=64, body=White, snow=White]};
そしてその後に、同じ位置にbody
無しの\scsnowman
を配置します。今度はsnow
に輪郭線の色を指定します。
\node at (232,248) {\scsnowman[scale=64,
muffler=Red, hat=Green, buttons=RoyalBlue, arms=Brown,
snow=SkyBlue]};
全体のソースコードは以下のようになりました。
\documentclass{standalone}
\usepackage[svgnames]{xcolor}
\usepackage{tikz,scsnowman}
\begin{document}
\begin{tikzpicture}[x=1bp,y=1bp]
\useasboundingbox (0,0) rectangle (480,360);
\fill[DarkGreen] (0,0) rectangle (480,40);
\fill[SkyBlue!5] (0,40) rectangle (480,360);
\shade[top color=SkyBlue!65, bottom color=SkyBlue!5]
(0,180) rectangle (480,360);
\node at (232,248) {\scsnowman[scale=64, body=White, snow=White]};
\node at (232,248) {\scsnowman[scale=64,
muffler=Red, hat=Green, buttons=RoyalBlue, arms=Brown, snow=SkyBlue]};
\end{tikzpicture}
\end{document}
意図通りになっているか、出力を確かめてみましょう。
ちゃんとフツーの☃画像が完成しました(幸せ😊)
※実は先に紹介した記事でもこの“裏技”が密かに使われています🙃
なお、先程の説明では“同じ場所に2つの☃を出力する”のをTikZのレベルで行いましたが、LaTeXでの一般的な“重ね書き”のテクニックを用いることもできます。こちらの方が使いやすい場合もあるでしょう。
\makebox[0pt][l]{\scsnowman[scale=64, body=White, snow=White]}
\scsnowman[scale=64,
muffler=Red, hat=Green, buttons=RoyalBlue, arms=Brown, snow=SkyBlue]};
まとめ
フツーの☃を出力してドンドン幸せ😊になりましょう!💁