マクロツイーター

はてダから移行した記事の表示が崩れてますが、そのうちに直せればいいのに(えっ)

LaTeXで和文を斜体する話(1)

まとめてみた。

なぜ和文を斜体しにくいのか

ほとんどの場合、日本語用のフォントには「斜体」の変種は用意されていない1。従って、和文を斜体で出力しようとすると「合成斜体」(直立体のグリフを変形して出力する)を使うことになる。TeXを利用したワークフローにおいても合成斜体は十分にサポートされているのであるが、あまり好まれていないこともあり、LaTeXユーザが簡単に使えるようにはなっていない。特に、「通常のフォント切り替え命令(\textit\slshape等)で和文に斜体が適用される」ような設定はほとんど行われないようである。

“図”として斜体する

斜体の使われ方に関する欧文と和文の間の大きな違いとして「和文の斜体は本文の段落を組むのに使われることが原則的にない」ということがある。つまり和文の斜体の用法の大部分は「図に類するもの(装飾性の高いもの)」ということになるだろう。そういう用法の場合、「フォントとしての斜体」ではなく「図の装飾としての斜体変形」を利用するのが妥当である。

TikZで図を作成する場合、テキストを配置するためにノード(node命令)を使うことになる。ここでnode命令のオプションとしてxslant=<割合>を指定すると、そのノードに斜体変形を適用できる。

例えば次のTikZの文は現在点に25%の斜体変形をかけた「テキスト」の文字を出力する。

\node[xslant=0.25] {テキスト};

※もちろん、ノードのテキストの内容は和文文字に限らない。

「斜体変形をかけた文字を含む図」の実例を挙げておく。

% upLaTeX+dvipdfmx
\documentclass[dvipdfmx]{article}
%↓単体の図を出力するための準備
\usepackage[papersize={400bp,320bp},
  margin=0pt,noheadfoot]{geometry}
\usepackage[svgnames]{xcolor}
\usepackage{tikz,scsnowman,tikzducks}
\setlength{\parindent}{0pt}
%↓既定のフォントを"原ノ味ゴシックHeavy"にする
\usepackage{lmodern,pxchfon}
\setminchofont{HaranoAjiGothic-Heavy.otf}
\newcommand{\myPeace}{\fontsize{64}{0}\rmfamily}
\begin{document}
\begin{tikzpicture}[x=1bp,y=1bp]
%↓この辺はいつものやつ☃
\useasboundingbox (0,0) rectangle (400,320);
\node at (100,100) {\scsnowman[scale=20,
  muffler=Red,hat=Green,buttons=RoyalBlue,
  arms=Brown,snow=SkyBlue]};
\node at (300,92) {\tikz[scale=60]{\duck[
  hat=Brown,cape=Orange]}};
%
%↓斜体変形をかけた文字を出力する
\node[text=Green,font=\myPeace,xslant=0.25]
  at (200,250) {世 界 平 和};
\end{tikzpicture}
\end{document}

f:id:zrbabbler:20200905142720p:plain
出力結果

TikZの図は段落の中に配置できる(“インライン”の要素である)ので、「図としての斜体」を“流用”する形で文章の一部を斜体の文字で出力することも可能である。ただし元来が図のための機能であるため、そういう使い方には少しコツが要る。詳しい説明は別の記事に譲ることにして、ここでは「斜体変形をかけたテキスト」を出力するマクロを挙げておく。

%% \mySlanted{テキスト}: テキストを25%斜体変形付で出力する.
\newcommand*{\mySlanted}[1]{\tikz[baseline=(T.base)]{%
  \node[inner sep=0pt,outer sep=0pt,xslant=0.25](T){#1}}}

この\mySlantedを使ったupLaTeX文書の例を挙げておく。

% upLaTeX+dvipdfmx
\documentclass[uplatex,dvipdfmx,a4paper]{jsarticle}
%↓ゴシック体を"原ノ味ゴシックBold"にする
\usepackage[haranoaji]{pxchfon}
\setgothicfont{HaranoAjiGothic-Bold.otf}
\usepackage{tikz}
\newcommand*{\mySlanted}[1]{\tikz[baseline=(T.base)]{%
  \node[inner sep=0pt,outer sep=0pt,xslant=0.25](T){#1}}}
\begin{document}
毎年9月21日は\mySlanted{\gtfamily 世界平和}の日☃です。
\end{document}

f:id:zrbabbler:20200905145027p:plain
出力結果

ただし、この方法には重大な欠点がある。単に「図を文章内に出力している」に過ぎないので、テキストを途中で改行することができないのである。従って、例えば「段落全体を斜体文字で出力したい」という場合2にはこの方法は使えず、きちんと「フォントとしての斜体」を用意する必要がある。

LuaLaTeXでフォントとして斜体する

LuaLaTeX(やXeLaTeX)ではfontspecの機能が使えるため、合成斜体のフォントを利用するのはそれほど難しくない。

fontspecの機能(\setmainfont\fontspec等)でフォントを定義する際に、パラメタにFakeSlant=割合を指定すると合成斜体が適用される。例えば、以下のコードは欧文フォントを25%斜体の「Comic Sans MS」に変更する。

% 欧文を25%斜体の"Comic Sans MS"にする
\fontspec{Comic Sans MS}[FakeSlant=0.25]

LuaTeX-jaで和文を扱っている場合は、luatexja-fontspecの命令(\setmainjfont\jfontspec等)を使って同様にFakeSlantを指定すれば合成斜体の和文フォントが利用できる。

% 和文を25%斜体の"HGS創英角ポップ体"にする
\jfontspec{HGSSoeiKakupoptai}[FakeSlant=0.25]

\newjfontfamilyを使って斜体の和文フォントを定義する例を挙げる。

% LuaLaTeX分署; UTF-8
\documentclass[a6paper]{ltjsarticle}
\usepackage{luatexja-fontspec}
% 斜体の"HGS創英角ポップ体"の和文フォント定義
\newjfontfamily{\myPoptai}{HGSSoeiKakupoptai}[FakeSlant=0.25]
\begin{document}
\myPoptai
日本國民は、正義と秩序を基調とする國際平和を誠實に希求し、
國權の發動たる戰爭と、武力による威嚇又は武力の行使は、
國際紛爭を解決する手段としては、永久にこれを放棄する。
\end{document}

f:id:zrbabbler:20200905161448p:plain
出力結果

「フォントをイタリック(\itshape)に変更した場合に和文に合成斜体が適用されるようにしたい」という場合は、ItalicFeaturesというパラメタを使って次のように指定できる。

% ItalicFeaturesの中に書いたパラメタはitshapeの時だけ
% 適用される
\newjfontfamily{\myPoptai}{HGSSoeiKakupoptai}
  [ItalicFeatures={FakeSlant=0.25}]

あるいは、この指定と等価になるAutoFakeSlantというパラメタも用意されている。

% itshapeを合成斜体にする
\newjfontfamily{\myPoptai}{HGSSoeiKakupoptai}[AutoFakeSlant=0.25]

AutoFakeSlantを指定して和文で合成斜体を有効にする例を挙げておく。

% LuaLaTeX分署; UTF-8
\documentclass[a6paper]{ltjsarticle}
\usepackage{luatexja-fontspec}
%↓itshapeを合成斜体にする
\setmainjfont{Harano Aji Mincho}[AutoFakeSlant=0.25]
\setsansjfont{Harano Aji Gothic}[AutoFakeSlant=0.25]
\usepackage{bxjalipsum}
\begin{document}

山路を登りながら、こう考えた。

智に働けば、\textit{ゆきだるま☃。}
情に棹させば、\textit{ゆきだるま☃。}
意地を通せば、\textit{ゆきだるま☃。}
\sffamily
とかくに人の世は、\textit{ゆきだるま☃。}

\end{document}

f:id:zrbabbler:20200905161513p:plain
出力結果

(もしかして続くかも)


  1. デザイン性の高いフォントの中には、元々斜体としてデザインされているものもある。

  2. アッ、さっき言った原則に反しているゾ!

tcspingifで“もっともっと”ゆきだるまを動かす

今日は「ホウキ付ゆきだるま☃」の日!

f:id:zrbabbler:20200818191245g:plain

先日の「ゆきだるま☃の日」にはLaTeXで「回転ゆきだるま☃画像」を作成するためのtcspingifというスクリプトを紹介した。tcspingifを使って作れる「回転☃」は「自転☃」であるが、少し(あるいは、かなり)頑張れば、上図のような「公転☃」、あるいはもっと別の動きを伴った「動く☃」のGIF画像をつくることもできる。その方法について解説する。

tcspingifはなぜ動くのか

tcfaspinパッケージはanimateパッケージの機能を使って「動くPDF文書」を作っているが、「動くPDF文書」は画像に変換できない。では、tcspingifはなぜGIF画像を作れるのかというと、実はtcfaspinの中に秘密がある。

tcfaspinを読み込む前に次のようなオマジナイを実行しておく。

\chardef\faStopTicks=18 \chardef\faAllTicks=32

TeX言語のコードなので理解する必要は全くないのだが、フインキとしては「\faStopTicks\faAllTicksという2つの“変数”を定義して、それぞれ18と32を“代入”する」のようなことを行っている1。このオマジナイが実行済である場合、tcfaspinパッケージはanimateを読み込まなくなり、また、\faSpin命令の動作が変わり、単に「32フレーム中の18フレーム目」の状態を出力するようになる。この場合に出力されるPDF文書はanimateを使っていないため普通にImageMagickで画像に変換できる。

この「tcfaspinの裏仕様」を利用して、tcfaspinは次のような手順で「動くGIF画像」を作っている。(フレーム数が32だとする。)

  • n=0~31の各々について:
    • 上記のオマジナイ(ただし\faStopTicksをnとする)を実行した上で対象のLaTeXソースをコンパイルして、普通のPDF文書を作る。
    • ImageMagickでPDF文書をPNG画像に変換する。これが「nフレーム目のPNG画像」となる。
  • 再びImageMagickを用いて、「0~31フレーム目のPNG画像」をアニメGIF画像に変換する。

tcfaspinしないでtcspingifする

このtcfaspinの実行手順をよく見ると、それ自体はtcfaspinとは無関係であることがわかる。すなわち、対象のLaTeX文書は別にtcfaspinを読み込んでいる必要はなく、単に「オマジナイが実行されて、“変数”が定義されている」という点だけが“普通のコンパイル”と異なるわけである。

これを利用すると、tcspingifを“流用”して好きな動き方をするアニメGIF画像をつくることができる。すなわち、LaTeX文書の内容を、「\faAllTicksフレーム中の\faStopTicksフレーム目」の状態を出力するようにすればよいのである。

pgfmathパッケージ2の機能を利用すると、“変数”の値を読み出すことができる3

% "変数" \faStopTicks の値を \vN に代入する
\pgfmathsetmacro{\vN}{\number\faStopTicks}
% \faStopTicks ÷ \faAllTicks の値を \vT に代入する
\pgfmathsetmacro{\vT}{\number\faStopTicks/\number\faAllTicks}

要するに要するに

以下のような感じでコードを書けばよい。

\documentclass{standalone}
\usepackage{tikz,pgfmath}
% \vT は"アニメの開始を0、終了を1とした場合の現在時刻"の値
\pgfmathsetmacro{\vT}{\number\faStopTicks/\number\faAllTicks}
% \vN は"現在何フレーム目か"の値
\pgfmathsetmacro{\vN}{\number\faStopTicks}
% (その他諸々の設定...)
\begin{document}
\begin{tikzpicture}
% \vT や \vN の値を利用して"現在のフレーム"を描画する
\end{tikzpicture}
\end{document}

※もちろん、このようにtcspingifを“流用”したLaTeX文書は「tcspingif専用」であり、普通にコンパイルして「動くPDF文書」をつくることはできないことに注意。
※tcfaspinを読み込まない場合、tcfaspinの設定からフレーム数を取得することができないため、tcspingifで--ticks(-t)オプションの指定が必須になる。

ゆきだるま☃を動かしてみる

※以下では、前回と同じく「DPI値を72にした(tcspingifで-d 72を指定)上でTikZでx=1bp,y=1bpを指定して座標の単位をピクセルと一致させる」設定を利用する。

手始めに、ゆきだるま☃を単純に横に動かしてみる。具体的に「600×120ピクセルの画像で、ゆきだるま☃を(60,60)から(540,60)に動かす」ことにする。先ほど示した雛形の\vT(現在時刻)を使うことにすると、ゆきだるま☃を置く点は「始点・終点間の\vT倍内分点」となる。calcライブラリの内分点表記を利用すると、tikzpicture内は以下のように書ける。

\node at ($(60,60)!\vT!(540,60)$) {
  \scsnowman[scale=15,hat,snow,arms,buttons,muffler=red]};

全体のソースは以下のようになる。

[sample01.tex]
% ↓以下のコマンドで変換
% tcspingif -e pdflatex -d 72 -t 32 -b 1 sample01.tex
\documentclass{standalone}
\usepackage{xcolor,tikz,pgfmath}
\usepackage{scsnowman}% ゆきだるま☃!
\usetikzlibrary{calc}% 内分点表記を使う
% \vT は"現在時刻"(0~1の範囲)
\pgfmathsetmacro{\vT}{\number\faStopTicks/\number\faAllTicks}
\begin{document}
\begin{tikzpicture}[x=1bp,y=1bp]
\useasboundingbox (0,0) rectangle (600,120);
\node at ($(60,60)!\vT!(540,60)$) {
  \scsnowman[scale=15,hat,snow,arms,buttons,muffler=red]};
\end{tikzpicture}
\end{document}

このLaTeXソースを以下のコマンドで画像に変換する。

tcspingif -e pdflatex -d 72 -t 32 -b 1 sample01.tex

※以下、ソースリストの先頭のコメントに変換用のコマンドラインを載せる。

実際に画像を表示して結果を確認してみよう。

f:id:zrbabbler:20200818191540g:plain

これで「自分で動きを定義する」ことができた。あとは“\vTと描画の間の処理”を適宜増やしていくことで、好きな動きを表現するだけである。

まずは「ゆきだるま☃が始点と終点の間を往復する」ようにしてみよう。pgfmathの式の三項演算子を利用して、「\vTが0→1を動くと、\vAが0→1→0と動く」ような新たな変数\vAを定義する。

\cLet{\vA}{(\vT<0.5) ? 2*\vT : 2-2*\vT}

あとは、\nodeの座標において、\vTの代わりに\vAを使う。

\node at ($(60,60)!\vA!(540,60)$) {

全体のソースは以下の通り。ここで、\pgfmathsetmacroという命令名は長いので、\cLetというマクロで別名定義している。

[sample02.tex]
% tcspingif -e pdflatex -d 72 -t 32 -b 1 sample02.tex
\documentclass{standalone}
\usepackage{xcolor,tikz,pgfmath,scsnowman}
\newcommand{\cLet}{\pgfmathsetmacro}
\usetikzlibrary{calc}
\cLet{\vT}{\number\faStopTicks/\number\faAllTicks}
\cLet{\vA}{(\vT<0.5) ? 2*\vT : 2-2*\vT}
\begin{document}
\begin{tikzpicture}[x=1bp,y=1bp]
\useasboundingbox (0,0) rectangle (600,120);
\node at ($(60,60)!\vA!(540,60)$) {
  \scsnowman[scale=15,hat,snow,arms,buttons,muffler=red]};
\end{tikzpicture}
\end{document}

f:id:zrbabbler:20200818191556g:plain

今度は「ゆきだるま☃の動きをもう少し自然にする」ために、水平位置の変数\vA\vTの二次関数に変えてみる。

\cLet{\vB}{(\vT<0.5) ? 2*\vT : 2-2*\vT}
\cLet{\vA}{(\vA<0.5) ? 2*\vB*\vB : -2*\vB*\vB+4*\vB-1}
[sample03.tex]
% tcspingif -e pdflatex -d 72 -t 32 -b 1 sample03.tex
\documentclass{standalone}
\usepackage{xcolor,tikz,pgfmath,scsnowman}
\newcommand{\cLet}{\pgfmathsetmacro}
\usetikzlibrary{calc}
\cLet{\vT}{\number\faStopTicks/\number\faAllTicks}
\cLet{\vB}{(\vT<0.5) ? 2*\vT : 2-2*\vT}
\cLet{\vA}{(\vA<0.5) ? 2*\vB*\vB : -2*\vB*\vB+4*\vB-1}
\begin{document}
\begin{tikzpicture}[x=1bp,y=1bp]
\useasboundingbox (0,0) rectangle (600,120);
\node at ($(60,60)!\vA!(540,60)$) {
  \scsnowman[scale=15,hat,snow,arms,buttons,muffler=red]};
\end{tikzpicture}
\end{document}

f:id:zrbabbler:20200818191616g:plain

さらに、ゆきだるま☃に回転を加えてみよう。これは\node命令にrotateパラメタを追加するだけである。

[sample04.tex]
% tcspingif -e pdflatex -d 72 -t 32 -b 1 sample04.tex
\documentclass{standalone}
\usepackage{xcolor,tikz,pgfmath,scsnowman}
\newcommand{\cLet}{\pgfmathsetmacro}
\usetikzlibrary{calc}
\cLet{\vT}{\number\faStopTicks/\number\faAllTicks}
\cLet{\vB}{(\vT<0.5) ? 2*\vT : 2-2*\vT}
\cLet{\vA}{(\vA<0.5) ? 2*\vB*\vB : -2*\vB*\vB+4*\vB-1}
\begin{document}
\begin{tikzpicture}[x=1bp,y=1bp]
\useasboundingbox (0,0) rectangle (600,120);
\node[rotate=-360*\vA] at ($(60,60)!\vA!(540,60)$) {
  \scsnowman[scale=15,hat,snow,arms,buttons,muffler=red]};
\end{tikzpicture}
\end{document}

f:id:zrbabbler:20200818191635g:plain

もっと動かしてみる

某ZR氏のツイッタァーでよくみるやつ

「無限に並んだゆきだるま☃が流れている」画像。

  • ゆきだるま☃を8つ横に並べる。
  • その上で、ゆきだるま☃6つ分の大きさの“ビューポート”を右方向に移動させる。これで、ゆきだるま☃が左に流れているように見える。
  • 開始時と終了時の状態を同じにしておくと、アニメガ反復したときに、ゆきだるま☃が滞りなく流れているように見える。
[sample05.tex]
% tcspingif -e pdflatex -d 72 -t 32 -b 1.5 sample05.tex
% ↑少し速度を上げた
\documentclass{standalone}
\usepackage{xcolor,tikz,pgfmath,scsnowman}
\newcommand{\cLet}{\pgfmathsetmacro}
\cLet{\vT}{\number\faStopTicks/\number\faAllTicks}
\begin{document}
\begin{tikzpicture}[x=1bp,y=1bp]
% ビューポート左下座標を (0,0)→(200,0) と動かす.
% "+(...)"は相対指定.
\useasboundingbox (200*\vT,0) rectangle +(600,120);
% 赤マフラー☃と青マフラー☃を交互に4回描く
\foreach \vJ in {0,...,3} {
  \node at (50+200*\vJ,60) {
    \scsnowman[scale=14,hat,snow,arms,buttons,muffler=red]};
  \node at (150+200*\vJ,60) {
    \scsnowman[scale=14,hat,arms,buttons,muffler=blue,
        sweat,mouthshape=tight]};
}
\end{tikzpicture}
\end{document}

f:id:zrbabbler:20200818191651g:plain

増殖ゆきだるま☃

“現在時刻”ではなく“現在何フレーム目か”の値を利用した例。

% \vN は"現在何フレーム目か"の値
\pgfmathsetmacro{\vN}{\number\faStopTicks}
  • フレーム数を5とする。
  • nフレーム目(n=0~4)で「n+1個のゆきだるま☃」を描く。
[sample06.tex]
% tcspingif -e pdflatex -d 72 -t 5 -b 1 sample06.tex
% ↑フレーム数(-t)は5で固定
\documentclass{standalone}
\usepackage[svgnames]{xcolor}
\usepackage{tikz,pgfmath,scsnowman}
\newcommand{\cLet}{\pgfmathsetmacro}
% \vN は"現在何フレーム目か"の値
\cLet{\vN}{\number\faStopTicks}
\begin{document}
\begin{tikzpicture}[x=1bp,y=1bp]
\useasboundingbox (0,0) rectangle (600,120);
\foreach \vJ in {0,...,\vN} {% 上限が \vN
  \node at (60+120*\vJ,60) {
    \scsnowman[scale=15,muffler=Red,hat=Green,
        buttons=RoyalBlue,arms=Brown,snow=SkyBlue]};
}
\end{tikzpicture}
\end{document}

f:id:zrbabbler:20200818191730g:plain

ゆきだるま☃ウェーブ

pgfmathでは初等関数が利用できるので、sin関数を使った例。

[sample07.tex]
% tcspingif -e pdflatex -d 72 -t 32 -b 1.5 sample07.tex
\documentclass{standalone}
\usepackage{xcolor,tikz,pgfmath,scsnowman}
\newcommand{\cLet}{\pgfmathsetmacro}
\cLet{\vT}{\number\faStopTicks/\number\faAllTicks}
\begin{document}
\begin{tikzpicture}[x=1bp,y=1bp]
\useasboundingbox (0,0) rectangle (600,120);
\foreach \vJ in {0,...,9} {
  % xcolorの混合率の値, 100→0 と動く.
  \cLet{\vC}{100*(1-\vJ/9)}
  % 垂直変位. 水平位置と時刻で決まる.
  \cLet{\yD}{30*sin(360*(\vJ/9+\vT))}
  \node at (30+60*\vJ,60+\yD) {
    \scsnowman[scale=9,arms,buttons,
      muffler=red!\vC!blue,hat=red!\vC!blue!75!black]};
}
\end{tikzpicture}
\end{document}

f:id:zrbabbler:20200818191705g:plain

もっともっと動かしてみる

過去にツイッタァーなどで披露した「動く☃画像」のソースを出しておく。

世界平和

[sample08.tex]
% tcspingif -e pdflatex -d 200 -t 32 -b 0.5 sample08.tex
% ↓200dpiで480×480ピクセルになるように調整
\documentclass[margin=1.36bp]{standalone}
\usepackage{xcolor,tikz,pgfmath}
\usepackage{scsnowman,tikzducks}
\definecolor{mc0}{rgb}{0.8,0,0}
\definecolor{mc1}{rgb}{0.5,0.3,0}
\definecolor{mc2}{rgb}{0.2,0.6,0}
\definecolor{mc3}{rgb}{0,0.7,0.1}
\definecolor{mc4}{rgb}{0,0.4,0.4}
\definecolor{mc5}{rgb}{0,0.1,0.7}
\definecolor{mc6}{rgb}{0.2,0,0.6}
\definecolor{mc7}{rgb}{0.5,0,0.3}
\scsnowmandefault{hat,arms,buttons,snow,scale=6}
\newcommand{\cLet}{\pgfmathsetmacro}
\cLet{\vT}{\number\faStopTicks/\number\faAllTicks}
\cLet{\vD}{\vT*360}
\pagecolor{black!0.5}
\begin{document}%↓座標単位は既定のまま(1cm)
\begin{tikzpicture}
\useasboundingbox (-3,-3) rectangle (3,3);
\node at (-  0+\vD:2) {\scsnowman[muffler=mc0]};
\node at (- 45+\vD:2) {\scsnowman[muffler=mc1]};
\node at (- 90+\vD:2) {\scsnowman[muffler=mc2]};
\node at (-135+\vD:2) {\scsnowman[muffler=mc3]};
\node at (-180+\vD:2) {\scsnowman[muffler=mc4]};
\node at (-225+\vD:2) {\scsnowman[muffler=mc5]};
\node at (-270+\vD:2) {\scsnowman[muffler=mc6]};
\node at (-315+\vD:2) {\scsnowman[muffler=mc7]};
\node at (0,0) {\tikz[scale=0.4]{\duck}};
\end{tikzpicture}
\end{document}

f:id:zrbabbler:20200818191843g:plain

フルパワー清涼感

これは普通にtcfaspinを使っている。

[sample09.tex]
% tcspingif -e pdflatex -d 72 -t 32 -b 3 sample09.tex
\documentclass{standalone}
\usepackage{ifthen,xcolor,tikz,pgfmath,scsnowman}
\newcommand{\cLet}{\pgfmathsetmacro}
\pagecolor{blue!30!green!6}%←背景色
\colorlet{coolhat}{blue!80!green!75!black}
\colorlet{coolmuffler}{blue!50!green}
\colorlet{coolarms}{green!30!black!50}
\colorlet{coolsnow}{blue!80!green!40}
\usepackage{tcfaspin}%←回します☃
\newcommand\cESnowman[1]{%
  \cPutSnowman{muffler=coolmuffler,hat=coolhat,#1}}
\newcommand\cOSnowman[1]{%
  \cPutSnowman{muffler=coolhat,hat=coolmuffler,#1}}
\newcommand\cPutSnowman[1]{%
  \node at (\vX*100+50,\vY*100+50) {%
    \faSpin{\scsnowman[%
      scale=10,arms=coolarms,snow=coolsnow,buttons=coolsnow,
      #1]}};}
\begin{document}
\begin{tikzpicture}[x=1bp,y=1bp]
\useasboundingbox (0,0) rectangle (600,600);
\foreach \vX in {0,1,...,5}
  \foreach \vY in {0,1,...,5} {
    % pgfmathの条件演算子だけだと実行の分岐ができないので
    % ifthenを併用する. ただし, \ifthenelse の条件文には
    % 式が書けず不便なので, "pgfmathで真偽値を求めて変数に
    % 入れて \ifthenelse でそれを見る"ことにする.
    \cLet{\vBroom}{\vX==5 && \vY==2}
    \cLet{\vNote}{\vX==4 && \vY==4}
    \cLet{\vOdd}{isodd(\vX+\vY)}
    \ifthenelse{\vBroom>0}{% ホウキ付き
      \cOSnowman{broom=coolarms!75!black}
    }{\ifthenelse{\vNote>0}{% ♪付き
      \cESnowman{note=coolsnow!90}
    }{\ifthenelse{\vOdd>0}{
      \cOSnowman{}
    }{\cESnowman{}}}}
  }
\end{tikzpicture}
\end{document}

f:id:zrbabbler:20200818192013g:plain

ホウキ付きゆきだるま☃の日のやつ

[sample10.tex]
% tcspingif -e pdflatex -d 72 -t 64 -b 0.5 sample10.tex
\documentclass{standalone}
\usepackage{xcolor,tikz,pgfmath,scsnowman}
\usepackage{type1cm}
%↓アホなフォント
\newcommand*{\fAho}{\usefont{OT1}{cmfr}{m}{it}{}}
\newcommand*{\cSize}[1]{\fontsize{#1}{0}\selectfont}
\definecolor{mydbrown}{rgb}{0.3,0.0,0.0}
\definecolor{mylbrown}{rgb}{0.7,0.5,0.0}
\newcommand{\cLet}{\pgfmathsetmacro}%
\cLet{\vT}{\number\faStopTicks/\number\faAllTicks}
\cLet{\vOR}{6}% ☃の軌道の半径
\cLet{\yW}{-2}% ☃のy座標
\cLet{\vD}{2}% キャンバスの位置(z=−2にある)
\cLet{\vA}{\vT*360+2}% 軌道上の角度
%↑開始時に中央に見えるように開始地点を補正している
\cLet{\zW}{\vOR*(1-cos(\vA))}% ☃のz座標
\cLet{\xW}{\vOR*(sin(\vA))}% ☃のx座標
\cLet{\vCS}{\vD/(\vD+\zW)}% (一点透視による倍率)
\cLet{\xC}{\vCS*\xW}% ☃のキャンバス上x座標
\cLet{\yC}{\vCS*\yW}% ☃のキャンバス上y座標
\cLet{\vSS}{\vCS*24}% ☃のキャンバス上の大きさ
%↑実際の大きさ(scale)が24
\newcommand{\cSnowman}[1]{%
  \scsnowman[scale=#1,
    arms=mydbrown,muffler=red,broom=mylbrown]}
\begin{document}
\begin{tikzpicture}[x=1bp,y=1bp]
  \useasboundingbox (0,0) rectangle (256,320);
  \node at (\xC*50+128,\yC*50+286) {\cSnowman{\vSS}};
  %↓例の日めくりカレンダーのアレ
  \node at (128,260) {%
    \cSize{29}\fAho August};
%  \node at (128,168) {%
%    \cSize{190}\fAho 18};
  \node[text=black!50] at (128,68) {%
    \cSize{10}\fAho Broom Snowman Day};
  \node at (128,33) {%
    \cSize{33}\fAho Tuesday};
\end{tikzpicture}
\end{document}

f:id:zrbabbler:20200818191245g:plain

Happy Snowman’s Day☃

[snowmansday2020.tex]
% tcspingif.pl -e pdflatex -t 64 -d 108 snowmansday2020.tex
\documentclass{standalone}
\usepackage[T1]{fontenc}
\usepackage{lmodern,pifont}
\usepackage{xcolor,scsnowman,tikzducks,pgfmath}
\newcommand*{\cLet}{\pgfmathsetmacro}
\setlength{\unitlength}{1bp}
%↓背景色
\colorlet{bgcolor}{blue!30!green!10}
\pagecolor{bgcolor}
%
\cLet{\xCS}{80}\cLet{\yCS}{320}% キャンバスサイズ
\cLet{\vT}{\number\faStopTicks/\number\faAllTicks}
\cLet{\vST}{(\vT-0.5)*2}
\cLet{\yH}{\yCS-\xCS}
\cLet{\xT}{\xCS/2}% ☃のx座標
%↑ただし実際にはずらして(2つ)置いている
\cLet{\yT}{\yH+\xCS/2-\yH*\vST*\vST}% ☃のy座標
%↑時刻の二次関数
\cLet{\vEA}{exp(\vST*5)}\cLet{\vEB}{exp(\vST*(-5))}
\cLet{\vRA}{((\vEA-\vEB)/(\vEA+\vEB)*0.5+0.5)*4}% 回転
%↑時刻をアフィン変換してtanhしたもの. 4回転している.
\cLet{\vRB}{mod(round(\vRA*1800)/5,360)}% 回転(度数)
%↑0.2度の整数倍に丸めた
%
\newcommand{\cTwo}{% アヒル的"2"
  \makebox(0,0){\tikz[scale=0.24]{\duck[%
    body=blue!50!green,bill=blue!50!green]}}}
\newcommand{\cZero}{% 雪結晶的"0"
  \fontsize{16}{0}\selectfont
  %↓重ね書きはイマイチ
  \makebox(0,1){\color{blue!50!green}\ding{108}}%
  \makebox(1,0){\color{bgcolor}\scalebox{0.8}{\ding{93}}}}
%
\begin{document}%↓なんとpicture環境
\begin{picture}(400,360)(0,-20)
\put(120,\yT){\makebox(0,0){\rotatebox[origin=c]{-\vRB}{%
  \scsnowman[hat=blue!80!green!75!black,
    muffler=blue!50!green,
    arms=green!30!black!50,
    snow=blue!80!green!40,
    scale=12]}}}
\put(280,\yT){\makebox(0,0){\rotatebox[origin=c]{\vRB}{%
  \scsnowman[hat=blue!50!green,
    muffler=blue!80!green!75!black,
    arms=green!30!black!50,
    snow=blue!80!green!40,
    scale=12]}}}
\put(200,260){\makebox(0,0){\textcolor{blue!50!green!60}{%
  \fontsize{48}{0}\sffamily\bfseries\ding{100}}}}
\put(200,200){\makebox(0,0){\textcolor{blue!85!black}{%
  \fontsize{28}{40}\sffamily\bfseries\itshape
  {Happy Snowman's Day}}}}
\put(200,144){\cTwo}
\put(200,112){\cZero}
\put(200,080){\cTwo}
\put(200,048){\cZero}
\end{picture}
\end{document}

f:id:zrbabbler:20200818192052g:plain


  1. TeX言語者向け解説】整数定数として用いるために、制御綴\faStopTicksを値18をもつchardefトークンと定義している。\faAllTicksも同様。

  2. TikZを読み込むとpgfmathが内部で読み込まれるので、この機能を利用するのが手っ取り早いだろう。(そして、scsnowmanパッケージはTikZを内部で読み込む。)

  3. TeX言語者向け解説】\faStopTicksはchardefトークンであるため\number\faStopTicksを1回展開するとその整数値の十進数字列に展開される。pgfmathの式の中で「数字列に展開されるトークン列は数値として扱われるため、この方法で値が読み出せるわけである。ちなみに、chardefトークンそのものはpgfmathの式の中で数値として扱われない。

Pandocで節見出しの“番号の書式”を変えたい話

元ネタはこの辺。

要するに「節見出しの中の番号の書式を変えるにはどうすればよいか」という話。

やりたいこと

Markdown文書をPandocでLaTeXやHTMLに変換する場合に、「節見出しの中の番号の書式」を以下のようにしたい。

  • 章(レベル1)については「第1章」とする。
  • 節(レベル2)については「第1節」とする(章番号はつけない)。

例えばこんなMarkdown文書があったとする。

# まえがき {-}
# ゆきだるま
## ゆきだるまは素敵
## ゆきだるまは本質的
## TeXとの関係 {-}

{-}は節見出しにunnumberedクラスを指定する記法({.unnumbered}と等価)で、番号のない節見出しであることを表す。

この文書の変換結果は以下のようになってほしい。

まえがき
第1章  ゆきだるま
第1節  ゆきだるまは素敵
第2節  ゆきだるまは本質的
TeXとの関係

LaTeXする場合

LaTeX脳で考える

LaTeXの思想に依って考えると、「節見出しの中の番号の書式」は文書クラスの専管事項ということになる。従って、書式を自分好みに変えたいのであれば、そういう文書クラスをつくればよい、という単純な話になる。

ただ、「単純な話」といっても「簡単な話」では決してない。文書クラスを作製(改変)するにはTeX言語の知識が多少とも必要となるからである。そこで、文書クラスによっては多少のカスタマイズを可能としていることがある。例えば、章(\chapter)については、多くの和文文書クラスにおいて、「章の数字(カウンタ表示)の前後に付く文字列」はマクロ(\prechaptername\postchaptername)になっていて変更できる。なので、要件によっては既存のクラスのカスタマイズで済む場合もあるだろう。

この辺りの話は、「PandocでLaTeX文書を生成する」場合であっても基本的には変わらない。Pandocの思想では原則的に「文書の構造を含めた内容だけを変換対象対象とし、文書のレイアウトについては変換先のソフトウェアに委ねる」ことになっているからである。ただしここでも例外があり、(主に複数の文書形式の間で統一的に扱う目的で)一部のレイアウト設定はPandoc側で制御できる。今回の件に関しては、LaTeX出力で標準のテンプレートを適用する場合は以下の機能が存在する。

  • --number-sectionsオプション(短縮名-N)が指定されない場合、節番号の表示を抑止するためにsecnumdepthカウンタの値に負数を設定する。

従って、要件を実現するには、「--number-sectionsを指定した上で、LaTeXの側で節番号表示に対してカスタマイズを行う」という方針をとることになる。

やってみる

いつも通り、BXJSクラスのPandocモードを利用する。今回は章がある文書なのでbxjsbookを使うことになる。

章番号の設定については、bxjsbookクラスも他の和文クラスと同様に\prechaptername\postchapternameマクロで行う。

\renewcommand{\prechaptername}{}
\renewcommand{\postchaptername}{}

ただし、(これも多くの和文クラスと同様で)上に示した値は既定値になっているので実際には何も設定しなくてよい。

節(\section)の番号については、BXJSクラスの独自機能(詳細は過去の記事を参照されたい)を利用する。すなわち、クラスオプションにlabel-section=modernを指定すた上で、以下のようにマクロを再定義する。

% 節のカウンタの表示に章の番号を入れない
\renewcommand{\thesection}{\arabic{section}}
% 節番号の出力を"第1節"とする
\renewcommand{\labelsection}{\thesection}

その他諸々の設定と合わせて、Pandocのデフォルトファイルの形にまとめたものを以下に示す。

to: latex-smart
standalone: true
pdf-engine: lualatex

top-level-division: chapter
number-sections: true

variables:
  papersize: b5
  secnumdepth: 2
  documentclass: bxjsbook
  classoption:
    - pandoc
    - label-section=modern
  header-includes: |
    \renewcommand{\thesection}{\arabic{section}}
    \renewcommand{\labelsection}{第\thesection 節}

f:id:zrbabbler:20200814181729p:plain
LaTeXに変換したやつ(第1章の部分)

HTMLする場合

Pandocで節番号するとアレ

Pandocで--number-sections付きでHTMLに変換した場合、以下のような出力が得られる。

<h1 class="unnumbered" id="まえがき">まえがき</h1>
<h1 data-number="1" id="ゆきだるま"><span class="header-section-number">1</span> ゆきだるま</h1>
<h2 data-number="1.1" id="ゆきだるまは素敵"><span class="header-section-number">1.1</span> ゆきだるまは素敵</h2>
<h2 data-number="1.2" id="ゆきだるまは本質的"><span class="header-section-number">1.2</span> ゆきだるまは本質的</h2>
<h2 class="unnumbered" id="texとの関係">TeXとの関係</h2>
<h2 data-number="1.3" id="マフラー"><span class="header-section-number">1.3</span> マフラー</h2>
<h2 data-number="1.4" id="ホウキ"><span class="header-section-number">1.4</span> ホウキ</h2>

ここで注意すべきなのは、「出力のHTMLの中に節番号が記述されている」ということである。つまり、LaTeX変換の場合と異なり、Pandoc側が番号を生成しているわけであり、先述の「Pandocの思想」にも反している。

※もちろん、--number-sectionsを付けない場合は節番号は入らない。

“思想に合わない”ということもあってか、Pandocの「節番号の自動生成」の機能は中途半端で、番号の書式を変えるためのインタフェースは用意されていないようである。つまり、HTML出力の場合は、Pandoc本体の機能だけでは要件は実現できないのである。

HTMLをLaTeX脳で考える

「Pandocの思想」に沿って考えるならば、「節番号の書式」については“HTMLの側”で対処すべきであろう。HTMLの世界で“文書クラス”に相当するものはCSSである。実際、CSSには「節番号を自動生成して節見出しに表示する」ための機能が存在する。

  • 節番号の生成はCSSカウンタを利用するとできる。
  • 節番号の表示は擬似要素を利用する。この際に、番号の書式を自由に設定できる。

従って、Pandocの側では節番号を生成せず(--number-sectionsを指定しない)、代わりに、CSSを利用して所望の書式の節番号を出力する、というのが“Pandoc的に真っ当な”方法といえるだろう。

今の場合、節番号の生成のためのスタイル指定は以下のようになる。

[sample.css]
/** 章のカウンタ"chapter"と節のカウンタ"section"を用意する **/
body {
  counter-reset: chapter, section;
}
/** 章見出しではchapterを増やしてsectionをリセット **/
h1 {
  counter-increment: chapter;
  counter-reset: section;
}
/** 節見出しではsectionを増やす **/
h2 {
  counter-increment: section;
}
/** "unnumbered"クラスの見出しでは何もしない **/
.unnumbered {
  counter-increment: none;
}

節番号の表示は以下のようになる。

[sample.css(続き)]
/** 章見出しの内容の前に"第1章"の形式で章番号を挿入 **/
h1::before {
  content: "第" counter(chapter) "章 ";
}
/** 節見出しの内容の前に"第1節"の形式で節番号を挿入 **/
h2::before {
  content: "第" counter(section) "節 ";
}
/** "unnumbered"クラスの見出しでは出力しない **/
.unnumbered::before {
  content: ""
}

Pandoc側の設定をデフォルトファイルで表すと以下の通り。

standalone: true
css: sample.css
number-sections: false

f:id:zrbabbler:20200814194512p:plain
HTMLに変換したやつ(第1章の部分)

実際には、「既定のテンプレートを指定した場合、文書のタイトルが“titleクラス付きのh1要素”で出力されるので、そのための対処が必要」といった問題がある。(まあ、実用で既定テンプレートを指定することはあまりないのかも知れないが。)その辺りの対処も加えたサンプル一式をGistに置いた。

厳しい現実の話

自分としては、これで満足なのであるが、しかし現実問題としては、CSSの素敵な機能を使おうとする場合には常に「その機能は世の中で十分にサポートされているのか」ということに留意しておく必要がある。

CSSの素敵な機能がサポートされていない環境のことも考慮する必要があるのなら、残念ながら結局、「Pandoc側で節番号を生成してHTMLのソースに入れておく」しかないことになる。

どうにかしてどうにかする

結局、Pandocが生成する節番号の書式を設定する機能はないのであるが、だとしても、節見出しがもつ「節番号表示のデータ」をフィルタを使って上書きすることはできないか。いろいろ調べてみた結果、次のことがわかった。

  • 節見出しのオブジェクト(Header型)の属性(attributes)のnumberに文字列を設定しておくと、writerの処理において、Pandocが生成した文字列の代わりにnumberの文字列が「節番号表示の文字列」として使用される1

ということは、「自分で好きな節番号文字列を生成してそれをnumber属性に格納する」ようなフィルタを作れば解決することになる。

[numbering.lua]
local numbers = {}
-- 節番号のスタイル
local number_styles = {
  -- この配列のn番目の要素に"レベルnの節番号表示"を返す関数を置く.
  -- 関数の実行時に, 配列numbersには現在の節番号の値が入っている.
  -- 例えば3.5節であればnumbersの値は {3,5} である.
  function() return ("第%s章"):format(numbers[1]) end;
  function() return ("第%s節"):format(numbers[2]) end;
}

function Header(el)
  -- 子カウンタをリセット
  if numbers[el.level+1] then
    numbers[el.level+1] = 0
  end
  -- .unnumbered なら変更しない
  if el.classes:includes("unnumbered") then
    return -- 変更しない
  end
  -- カウンタをインクリメント
  numbers[el.level] = (numbers[el.level] or 0) + 1
  -- 番号を生成し'number'属性に設定する
  el.attributes['number'] = number_styles[el.level]()
  return el
end

このフィルタを用いる場合のPandoc側の設定は以下の通り。

filters:
  - numbering.lua
standalone: true
number-sections: true

※今度は--number-sectionsを有効にする必要があることに注意。

この設定を適用してHTMLに変換した結果(のbody内)を示す。所望の節番号表示が入っていることがわかる。

<h1 class="unnumbered" id="まえがき">まえがき</h1>
<h1 data-number="第1章" id="ゆきだるま"><span class="header-section-number">第1章</span> ゆきだるま</h1>
<h2 data-number="第1節" id="ゆきだるまは素敵"><span class="header-section-number">第1節</span> ゆきだるまは素敵</h2>
<h2 data-number="第2節" id="ゆきだるまは本質的"><span class="header-section-number">第2節</span> ゆきだるまは本質的</h2>
<h2 class="unnumbered" id="texとの関係">TeXとの関係</h2>
<h2 data-number="第3節" id="マフラー"><span class="header-section-number">第3節</span> マフラー</h2>
<h2 data-number="第4節" id="ホウキ"><span class="header-section-number">第4節</span> ホウキ</h2>

実際にブラウザで表示したときの結果は前のもの(CSSを利用したもの)と全く同じになるので省略する。

まとめ


  1. Pandoc要素に属性を設定すると、HTMLに出力した際に、対応するHTML要素のデータ属性として値が現れる。先に挙げた「PandocのHTML出力」のコードをよくみると、h1・h2要素のdata-number属性に節番号文字列が入っていることがわかる。これは「writerの処理時にPandocのHeader要素のnumber属性に節番号文字列が入っていた」ことを意味している。ただし、節番号の生成はまさにwriterの処理の中で行われるため、フィルタ処理の中でnumber属性を読みだしても何も入っていない。

イマドキのWindowsでcomicsansパッケージする方法

前回の記事の続きで、LaTeXのcomicsansパッケージ(あるいは「Comic Sans MS」フォント)をイマドキのWindowsで使うための話。

イマドキのComic Sans MSだとcomicsansできない話

周知のとおり、Comic Sans MSはWindows(95から)に標準で搭載されているフォントである。comicsansパッケージのマニュアルの説明に従うと、comicsansは「Windowsに搭載されているComic Sans MS」もサポートしているはずである。

ところが、実際に現役のWindows(8.1以降)でマニュアル通りの手順(前回説明した手順からフォントファイルのダウンロードを省いたもの)に従ってインストールした上でcomicsansを利用しようとすると、コンパイルは通ってPDFが生成されるが、肝心のComic Sans MSの文字が全て化けてしまうという無残な結果になる。

f:id:zrbabbler:20200812005848p:plain

この原因は、要するに、「comicsansは古いパッケージ(最終更新は2013年)であり、Windows 8以降の新しいComic Sans MSフォントに対応できていない」からである。

イマドキのComic Sans MSでcomicsansする話

そこで、「comicsansを新しいフォントファイルに対応させるためのパッケージ」を作ってみた

comicsansの内容に変更を加えるのは避けたいので、「comicsansを内部で読み込む新たなパッケージ」という形で提供する。

tccomicsansのインストール方法

Windows 8以降が必要である1

  • comicsansパッケージをパッケージのファイルだけインストールする。すなわち、CTANからcomicsans.tds.zipをダウンロードして、$TEXMFLOCALの下でそのZIPファイルを展開する。
    ※既にcomicsansが完全にインストールされているならそれでもOK。
  • tccomissansのReleaseページから最新の“tccomicsans.tds.zip”(この名前のリンクがある)をダウンロードして$TEXMFLOCALの下でそのZIPファイルを展開する。
  • mktexlsrを実行する。(必要なら管理者権限で)

tccomicsansのキホン的な使い方

comicsansと同じ用法で使いたいのであれば、tccomicsansをmainオプションを付けて読み込む。

\usepackage[main]{tccomicsans}

注意として、tccomicsansはドライバ依存をもつ。従って、dvipdfmxと併用する場合はクラスオプション2dvipdfmxを指定する必要がある。

例えば、前回の記事のテスト用の文書と同等のものは、以下のソースファイルから得られる。

\documentclass{article} % pdfLaTeXの場合
%\documentclass[dvipdfmx]{article} % dvipdfmxの場合
\usepackage[main]{tccomicsans}
\begin{document}
\section{A Simple Test}
Hello, comic {\TeX} world!
\[ \lim_{x\to0}\frac{\sin x}{x} = 1 \]
\end{document}

f:id:zrbabbler:20200810094421p:plain

なお、新しいComic Sans MSフォントは以前のものとは異なり「イタリック」「太字イタリック」のフォントファイルが含まれている。tccomicsansパッケージのフォントマップはイタリックシェープに対して(合成斜体ではなく)これらのフォントファイルを割り当てているため、pdfLaTeXでもイタリックシェープが使用可能である。もちろん、キリル文字にも対応している。

% 文字コードはUTF-8
\documentclass{article} % pdfLaTeX
%\documentclass[dvipdfmx]{article} % dvipdfmx
%↓ロシア語したい
\usepackage[utf8]{inputenc}
\usepackage[T2A,T1]{fontenc}
\usepackage[russian,main=english]{babel}
\babeltags{RUS=russian}
%↑
\usepackage[main]{tccomicsans}
\begin{document}
\section{A \emph{Very} Simple Test}
\begin{itemize}
\item In \emph{America}, you run {\TeX}.
\item \textRUS{В \emph{Советской-России}, {\TeX} выполняет вас!}
\end{itemize}
\end{document}

f:id:zrbabbler:20200812025222p:plain

tccomicsansをホンキで使う

comicsansのオプション、例えばulemphlargesymbolsなどはtccomicsansでも有効である。(内部でcomicsansを読み込む際にこれらのオプションをそのまま渡している。)

\documentclass{article} % pdfLaTeX
%\documentclass[dvipdfmx]{article} % dvipdfmx
% 大型演算子をアレにする
\usepackage[main,largesymbols]{tccomicsans}
\begin{document}
\[ e = \lim_{t\to\infty} \left(
       1 + \frac{1}{t} \right)^t
     = \sum_{n=0}^{\infty} \frac{1}{n!}
\]
\end{document}

f:id:zrbabbler:20200812025203p:plain

tccomicsansパッケージのmainオプションは「comicsansパッケージを内部で読み込んで本文のメインのフォントをComic Sans MSに変更する」という設定を行うためのものである。従って、tccomicsansをmainを付けずに読み込んだ場合はメインのフォントの設定は変更されない。この場合に「comicというフォントファミリを利用すれば文書の一部だけComic Sans MSを適用できる」ということは前回の記事で述べたが、さらにtccomicsansパッケージでは次のユーザ命令が利用できる。

  • \comic: 以降のテキストをComic Sans MSで出力する。(普通はグルーピング内で使う。)
  • \textcomic{テキスト}: 引数のテキストをComic Sans MSで出力する。

mainが有効な場合もこれらの命令は提供される。
mainが無効な場合はcomicsansパッケージは読み込まれない。従って、comicsans用のオプション指定は無効になる。
※tccomicsansパッケージの仕様では、Comic Sans MSで実際に出力する場合には必ずパッケージを読み込む必要がある。(フォントマップを有効にするため。)

\documentclass{article} % pdfLaTeX
%\documentclass[dvipdfmx]{article} % dvipdfmx
\usepackage[nomain]{tccomicsans}
\begin{document}
% 一部だけComic Sans MSにする.
Hello, \textcomic{comic} {\TeX} world!
\end{document}

f:id:zrbabbler:20200810094451p:plain

LuaLaTeXとかXeLaTeXとか

fontspecパッケージの機能を利用してWindows付属のComic Sans MSを指定する場合は以下のようにする。

Windows上のTeX LiveではOSにインストールされたフォントはfontspecにおいて必ずフォント名で指定できる。ファミリ名だけ書けば済むのでフォント名指定のほうが便利であろう。

% LuaLaTeX/XeLaTeX
\documentclass{article}
\usepackage{fontspec}
% フォント名で指定する場合
\setmainfont{Comic Sans MS}
% ファイル名で指定する場合
%\setmainfont{comic}[Extension=.ttf,ItalicFont=*i,
%    BoldFont=*bd,BoldItalicFont=*z]
\begin{document}
Hello, comic {\TeX} world!
\end{document}

f:id:zrbabbler:20200810124233p:plain

前回の記事の最後に挙げた「Comic Sans MSの指定を、テキストはfontspec、数式はcomicsansで行う」例をtccomicsansを使って書き直すと以下のようになる。

% LuaLaTeX/XeLaTeX; UTF-8
\documentclass{article}
\usepackage[main]{tccomicsans}
\usepackage[no-math]{fontspec}
\setmainfont{Comic Sans MS}
\begin{document}
\section{\emph{Comic} Lua{\LaTeX}}
\begin{itemize}
\item \TeX-lingvo estas \emph{danĝera!}
\item \TeX-язык — \emph{опасен!}
\item Η γλώσσα \TeX\ είναι \emph{επικίνδυνη!}
\item $\displaystyle
  \frac{1}{1^2} + \frac{1}{2^2} + \frac{1}{3^2} + \cdots
  = \frac{\pi^2}{6}$.
\end{itemize}
\end{document}

f:id:zrbabbler:20200812035350p:plain

まとめ

イマドキのWindowsのComic Sans MSは用法・用量を守って(ry


  1. 実際には「Windows 8以降に搭載のものと同等なComic Sans MS」があればtccomicsansは使えるはずである。この場合、そのフォントファイルを「TeXから見える場所」に配置すればよい。

  2. ドライバオプションをtccomicsansのオプションとして指定することも可能であるが、イマドキのLaTeXを使っているのであれば、ドライバオプションはクラスオプション(グローバルオプション)に指定すべきである。

TeX Liveでcomicsansパッケージする方法

TeX Live(およびそれに準ずるTeX配布)で「comicsansパッケージ」をインストールする手順を説明してみる。

最初に注意してみる

  • Windowsでは当然Comic Sans MSが付属しているはずであるが、Windows 8以降に付属する新しい版のComic Sans MSについてはcomicsansパッケージはサポートしていないので使えない。ここで説明する手順に従って古い版のComic Sans MSを導入する方法はWindowsでも有効であるが、OSのフォントを古い版で上書きしてしまわないように十分に注意すること。
  • ★印を付けた操作は管理者権限(例えば“sudo”を付けるなど)が必要である。

手順を説明してみる

①comicsansのパッケージをダウンロードする

  • CTANのページを開く。
    CTAN: Package comicsans
  • “comicsans.tds.zip”のリンクから、その名前のファイルをダウンロードする。
    ※“Download”から得られる「comicsans.zip」ではないので注意。
  • “Package Documentation”のリンクをたどって、マニュアルを開く。
    ※あるいは、何らかの方法で、zip内にあるcomicsans.pdfを開く。

②マニュアルの手順に従う

2.1 Acquire and install the TrueType files
  • フォントファイル(comic.ttf、comicbd.ttf)の取得は書いてある通り。
  • ★フォントファイルを次の場所に配置する: $TEXMFLOCAL/fonts/truetype/microsoft/comicsans/
2.2 Generate the italic and/or Cyrillic variants (optional)
  • これは、TeX外のシステム依存の話なので、がんばる。あるいは、optionalなのでがんばらなくてもよい。

※マニュアルの説明の中に「cyrfinst package」なるものが登場するが、要するに、t2a.encがあればよく、TeX Liveのフルインストールなら入っているはずである。(kpsewhich t2a.encで確認できる。)ない場合は、TeX Liveのインストールにcollection-langcyrillicを追加する。(もちろん、キリル文字を使う予定がないなら不要。)

2.3 Install font files and refresh TeX’s database

この節に相当する手順は以下のようになる:

  • ★先ほどダウンロードしたcomicsans.tds.zipを$TEXMFLOCALの下で展開する。
  • ★2.2の手順を行った場合は、生成されたフォントファイル(*.pfb)を以下の場所に配置する:
    $TEXMFLOCAL/fonts/type1/microsoft/comicsans/
  • ★「mktexlsr」を実行する。

※Texdocが利用可能な場合、これ以降は「texdoc comicsans」でインストールしたcomicsans.pdfが開くようになるはず。

2.4 Point the TeX backends to the comicsans files

この節に相当する手順は以下のようになる:

  • ★「updmap-sys --enable Map comicsans.map」を実行する。

③動作確認する

以下のような簡単なテストファイルを用意する。

\documentclass{article}
\usepackage{comicsans}
\begin{document}
\section{A Simple Test}
Hello, comic {\TeX} world!
\[ \lim_{x\to0}\frac{\sin x}{x} = 1 \]
\end{document}

このソースファイルを、以下の各々のワークフローで普通にビルドして、正常にPDFが生成されるかを調べる。

  • pdflatex
  • (p)latex → dvipdfmx

成功の場合、以下の出力が得られるはずである。

f:id:zrbabbler:20200810094421p:plain

さらに蛇足してみる

Type1フォントを作らない方法

dvipdfmxの場合は、わざわざType1フォントに変換しなくても、元のTrueTypeフォントのままでイタリック(擬似斜体)を使うことができる。(pdfTeXでは不可。)その設定に変更する手順を示す。

※管理者権限が必要。

①まず、$TEXMFLOCAL/fonts/map/dvips/comicsans/comicsans.mapを開いて、31~32行目を以下のように書き換える。

(修正前)
rcomico8r ComicSansMS "0.167 SlantFont" <rcomic8r.pfb
rcomicbdo8r ComicSansMS-Bold "0.167 SlantFont" <rcomicbd8r.pfb
rcomiccyro ComicSansMS "0.167 SlantFont" <rcomiccyr.pfb
rcomiccyrbdo ComicSansMS-Bold "0.167 SlantFont" <rcomiccyrbd.pfb
(修正後)
rcomico8r ComicSansMS "0.167 SlantFont TeXBase1Encoding ReEncodeFont" <8r.enc <comic.ttf
rcomicbdo8r ComicSansMS-Bold "0.167 SlantFont TeXBase1Encoding ReEncodeFont" <8r.enc <comicbd.ttf
rcomiccyro ComicSansMS "0.167 SlantFont T2AAdobeEncoding ReEncodeFont" <t2a.enc <comic.ttf
rcomiccyrbdo ComicSansMS-Bold "0.167 SlantFont T2AAdobeEncoding ReEncodeFont" <t2a.enc <comicbd.ttf

②その上で、updmap-sysを(オプションなしで)実行する。

以下にサンプルを示す。

\documentclass{article}
\usepackage{comicsans}
\begin{document}
% \emph が斜体になる.
\section{A \emph{Very} Simple Test}
Hello, \emph{comic} {\TeX} world!
\end{document}

f:id:zrbabbler:20200810095855p:plain

文書の一部だけComic Sans MSにする

comicsansパッケージを読み込む(\usepackage{comicsans})と、文書のメインのフォントがComic Sans MSに変更されてしまうため、「メインのフォントは変えずに、文書の一部だけComic Sans MSを使いたい」という場合には対応できない。実は、comicsansをインストールした時点で、Comic Sans MSが「comic」という(NFSSの)ファミリ名で使えるようになっているので、一部だけ使いたい場合はパッケージを使用せずに直接ファミリを切り替えればよい。

\documentclass{article}
%% \textcomic{テキスト}: Comic Sans MSで出力する.
\newcommand{\textcomic}[1]{%
  {\fontfamily{comic}\selectfont #1}}
\begin{document}
% 一部だけComic Sans MSにする.
Hello, \textcomic{comic} {\TeX} world!
\end{document}

f:id:zrbabbler:20200810094451p:plain

まとめ

Comic Sans MSは用法・用量を守って正しく使いましょう(多分)。


追記:さらにさらに蛇足してみる

LuaLaTeXとかXeLaTeXとかの場合

もちろん、LuaLaTeX・XeLaTeXを使っているのなら、fontspecパッケージの機能を利用してComic Sans MSを利用できる。なので普通はそもそもcomicsansパッケージは不要である。

% LuaLaTeX/XeLaTeX
\documentclass{article}
\usepackage{fontspec}
% ファイル名で指定する場合
\setmainfont{comic.ttf}[BoldFont=comicbd.ttf]
% フォント名で指定する場合(環境依存)
%\setmainfont{Comic Sans MS}
\begin{document}
Hello, comic {\TeX} world!
\end{document}

f:id:zrbabbler:20200810124233p:plain

しかし、数式でComic Sans MSを使いたいのであれば、comicsansパッケージを使うのが妥当であろう1。この場合は、一般的な「fontspecと数式フォントパッケージと組み合わせる」場合のノウハウに従えばよい。つまり:

  • まず数式フォントパッケージ(つまりcomicsans)を読み込む。
  • 次にfontspecをno-mathオプションを付けて読み込む。これでテキスト用フォントはfontspecの初期設定に戻る(数式フォントパッケージの設定は消える)。
  • 改めてテキスト用フォントをfontspecの機能で設定する。
% LuaLaTeX/XeLaTeX
\documentclass{article}
\usepackage{comicsans}
\usepackage[no-math]{fontspec}
\setmainfont{comic.ttf}[BoldFont=comicbd.ttf]
\begin{document}
Hello, comic {\TeX} world and $e^{\pi i} = -1$.
\end{document}

f:id:zrbabbler:20200810124259p:plain

ただし注意がある。この設定では、テキスト用フォントについてはfontspecの機能を使って「TrueTypeフォントを直接指定している」ので、マップファイル(comicsans.map)の設定は使われていない2。なので、イタリックの指定は無効になる。合成斜体によるイタリックを有効にするには、fontspecのFakeSlant指定を利用すればよい3

% ファイル名で指定する場合
\setmainfont{comic}[Extension=.ttf,
    BoldFont=*bd,
    ItalicFont=*,ItalicFeatures={FakeSlant=0.167},
    BoldItalicFont=*bd,BoldItalicFeatures={FakeSlant=0.167}]
% フォント名で指定する場合(環境依存)
%\setmainfont{Comic Sans MS}[
%    ItalicFont=*,ItalicFeatures={FakeSlant=0.167},
%    BoldItalicFont={* Bold},BoldItalicFeatures={FakeSlant=0.167}]

イタリックと数式を含む完全な形のサンプルを挙げておく。

% LuaLaTeX/XeLaTeX; UTF-8
\documentclass{article}
\usepackage{comicsans}
\usepackage[no-math]{fontspec}
\setmainfont{comic}[Extension=.ttf,
    BoldFont=*bd,
    ItalicFont=*,ItalicFeatures={FakeSlant=0.167},
    BoldItalicFont=*bd,BoldItalicFeatures={FakeSlant=0.167}]
\begin{document}
\section{\emph{Comic} Lua{\LaTeX}}
\begin{itemize}
\item \TeX-lingvo estas \emph{danĝera!}
\item \TeX-язык — \emph{опасен!}
\item Η γλώσσα \TeX\ είναι \emph{επικίνδυνη!}
\item $\displaystyle
  \frac{1}{1^2} + \frac{1}{2^2} + \frac{1}{3^2} + \cdots
  = \frac{\pi^2}{6}$.
\end{itemize}
\end{document}

f:id:zrbabbler:20200810125805p:plain


  1. Comic Sans MSは数式用のフォントではないため、unicode-mathパッケージを適用したのでは恐らくロクな結果にならない。comicsansの数式もアレであるが、多分そっちの方がマシだろう。

  2. マップファイルで指定したのは非Unicodeのエンジンのためのフォントの設定であり、それは8ビットのエンコーディングを前提にしているため、Unicodeエンジンでそれを用いることは(可能ではあるが)推奨されない。

  3. (Bold)ItalicFeaturesを効かせるためには(Bold)ItalicFontを明示指定する必要があるようだ。なんか面倒だ……。

LaTeXでつくる「回転ゆきだるまGIF画像」

今年は世界を襲った未曾有の疫病のため日常が……(中略)…………ゆきだるま☃!

LaTeXでつくる「ツイッタァーの進捗」

毎年恒例の「ゆきだるま☃の日」ですが、その日が近づくとツイッタァーに現れる「進捗を促す某ZR氏のツイート」もすっかりお馴染みのものとなりました(多分)。

くるくる回るゆきだるま☃をツイッタァーに上げるべき、というのは至極当然の提案ですね(多分)。

しかし、この提案に沿って、ツイッタァーに素敵な回転ゆきだるま☃のGIFアニメ画像を投稿しようとすると、すぐにある問題に気づくことでしょう。

回転ゆきだるま☃のGIFアニメ画像をどうやって作るか。

もちろん、回転ゆきだるま☃の画像をつくるツールや手法について何か指定があるわけではないので、GIFアニメ画像をつくるツールであれば何でも事足りるのは確かです。しかし、当ブログの読者の多くがLaTeXユーザであると思しきことを考えると、scsnowmanパッケージのカワイイゆきだるま☃を使ったLaTeXソースから回転ゆきだるま☃のGIFアニメ画像をつくることができたら最高に幸せであることは間違いないでしょう。

というわけで、今年の「ゆきだるま☃の日」の記事では、回転ゆきだるま☃画像をつくるスクリプトであるtcspingifを紹介します。

復習:LaTeXでつくる「回転☃文書」

LaTeXでゆきだるま☃を出力する方法は皆さんご存じでしょう。scsnowmanパッケージを利用すると、好きな色のマフラーや帽子を付けたゆきだるま☃を出力できます。

[sample-1.tex]
% pdfLaTeX文書; UTF-8
\documentclass{standalone}
\usepackage[svgnames]{xcolor}
\usepackage{scsnowman}% ゆきだるま☃!
\begin{document}
% 赤マフラーの素敵なゆきだるま☺
\scsnowman[scale=40,
  muffler=Red,hat=Green,buttons=RoyalBlue,
  arms=Brown,snow=SkyBlue]%
\end{document}

f:id:zrbabbler:20200808205518p:plain
sample-1の出力(非回転)
あるいは、「自分は『原ノ味フォント』の☃が好きだ」という人なら、XeLaTeX(やLuaLaTeX)1でfontspecパッケージを利用した上で、大きなフォントサイズで「☃」の文字を書けばよいでしょう。

[sample-2.tex]
% XeLaTeX文書; UTF-8
\documentclass[margin=10pt]{standalone}
\usepackage{xcolor,fontspec}
\setmainfont{Harano Aji Mincho}% 原ノ味明朝
\begin{document}
\fontsize{240}{0}\selectfont % サイズは240pt
\color{blue!60!black}%% ←素敵☺
\end{document}

f:id:zrbabbler:20200808205616p:plain
sample-2の出力(非回転)
これらの文書の出力は素敵ですが、しかし、回っていません。ゆきだるま☃を回転させるにはどうすればよいでしょうか。「LaTeXで何かを回転させる」ということなので、tcfaspinパッケージが使えそうです。

早速、ゆきだるま☃に\faSpin命令を適用してみましょう。

\faSpinを使用する場合、コンパイルを2回以上行う必要があります。

[sample-3.tex]
% pdfLaTeX文書; UTF-8
\documentclass[margin=25pt]{standalone}
\usepackage[svgnames]{xcolor}
\usepackage{scsnowman}% ゆきだるま☃!
\usepackage{tcfaspin}% 回転!
\begin{document}
% \scsnowman を回転させる
\faSpin{\scsnowman[scale=40,
  muffler=Red,hat=Green,buttons=RoyalBlue,
  arms=Brown,snow=SkyBlue]}%
\end{document}
[sample-4.tex]
% XeLaTeX文書; UTF-8
\documentclass[margin=25pt]{standalone}
\usepackage{xcolor,fontspec}
\setmainfont{Harano Aji Mincho}% 原ノ味明朝
\usepackage{tcfaspin}
\begin{document}
\fontsize{240}{0}\selectfont
\color{blue!60!black}%
\faSpin{}% ←回転!
\end{document}

これをAdobe Readerで開くと……。

f:id:zrbabbler:20200808205648g:plain
sample-3の出力(回転!)
f:id:zrbabbler:20200808205725g:plain
sample-4の出力(回転!)

ゆきだるま☃が回りました! 素敵ですね! というわけで、あとはツイッタァーに投稿するだけ……アッ、チョット待って。この回転ゆきだるま☃は確かに回っていますが、GIF画像ではなくてPDF文書なので、残念ながらこのままではツイッタァーに投稿できません。どうにかして、このPDF文書を画像ファイルに変換しないといけません。

LaTeXでつくる「回転☃画像」

回転☃をImageMagickできない話

PDF文書を画像ファイルに変換する方法としては、(特にTeX界隈では)ImageMagickがよく使われます。例えば、最初の例のsample-1.pdfをPNG画像に変換するには、magickコマンド2を使って次のようにします。

ImageMagickでPDFファイルを扱うにはGhostscriptを併せてインストールする必要があります。

# sample-1.pdf を sample-1.png に変換する(-density はDPI値指定)
> magick -density 72 sample-1.pdf sample-1.png

ImageMagick自体はアニメGIF画像にも対応していますが、残念ながら、tcfaspinを利用した「回るPDF文書」を直接「回るGIF画像」に変換することはできません。これはtcfaspinがかなり特殊な処理を行っているからです3。従って、tcfaspinを使ったLaTeXソースから「ツイッタァーに上げるための回転ゆきだるま☃画像」を生成することは困難です。

回転☃をImageMagickする話

このままでは「ツイッタァー上の回転ゆきだるま☃画像がいつまで経っても増えない」という由々しき事態になりかねません。この困難を打破するため、スクリプトつくりました

このPerlスクリプト tcspingif.pl の実行には以下のインストールが必要です。

tcspingif.pl を使うとコマンド1つで「tcfaspinを使ったLaTeX文書をアニメGIF画像に変換する」ことができます。例えば、先の例にあるsample-3.texとsample-4.texの場合、次のコマンドを実行することで、「PDF文書と同じ出力(同じ動き)」のGIF画像が得られます。

# pdfLaTeX文書 sample-3.tex をGIF画像 sample-3.gif に変換する
> perl tcspingif.pl -e pdflatex sample-3.tex
# XeLaTeX文書 sample-4.tex をGIF画像 sample-4.gif に変換する
> perl tcspingif.pl -e xelatex sample-4.tex

オプションは次の通りです(詳しくは--help付実行で出るヘルプを参照)。

  • -e <名前>: 使用するLaTeXのエンジン(コマンド名、例えばxelatex)。(既定値=pdflatex
    ※DVI出力のエンジン(platexなど)を指定した場合、PDFに変換するのにdvipdfmxが使われます。
  • -d <実数>: 出力解像度のDPI値。(既定値=72
  • -t <整数>: 1回転中のフレーム数。既定値はtcfaspinのオプションで指定された値で、さらにその既定値は32。
  • -b <実数>: 回転速度の標準に対する倍率。(既定値=1
    ※標準は「2秒で1回転」です4。ただし、アニメGIFのフレーム時間設定が10ミリ秒単位であるため実際には誤差が出ます。

チョット補足

生成される画像の大きさは元のPDF文書のものを引き継ぐので、大きさを調整したい場合は、standaloneクラスを利用した上で

  • standaloneのmarginオプションで適宜調節する
  • 文書本体を1つのpicture環境(の類、例えばTikZのtikzpicture環境)にしてその外形を所望のサイズに設定する

などの工夫をすればいいでしょう。

※以下、解像度指定(-dオプション)は72dpiとします。この場合、LaTeX内の1bpが1ピクセルに対応することになります。

例えば、sample-3.texではmarginの値は25ptとなっていますが、これを0ptに変えると出力の大きさは縦横309ピクセルとなります(そして回転の途中で一部が外にはみ出す)。これを縦横360ピクセルで出力するには、marginを25.5bpに指定すればよいことになります((360-309)÷2=25.5)。

[sample-5.tex]
% pdfLaTeX文書; UTF-8
\documentclass[margin=25.5bp]{standalone}
\usepackage[svgnames]{xcolor}
\usepackage{scsnowman}% ゆきだるま☃!
\usepackage{tcfaspin}% 回転!
\begin{document}
\faSpin{\scsnowman[scale=40,
  muffler=Red,hat=Green,buttons=RoyalBlue,
  arms=Brown,snow=SkyBlue]}%
\end{document}
# sample-5.tex をGIF画像 sample-5.gif に変換する
> perl tcspingif.pl -e pdflatex sample-5.tex

f:id:zrbabbler:20200808205648g:plain
sample-5の出力(回転GIF!)

同様に、sample-4.texを縦横280ピクセルで出力する場合は、以下のように調整することになります5

[sample-6.tex]
% XeLaTeX文書; UTF-8
\documentclass{standalone}
\standaloneconfig{margin={20.5bp 26bp}}
\usepackage{xcolor,fontspec}
\setmainfont{Harano Aji Mincho}% 原ノ味明朝
\usepackage{tcfaspin}
\begin{document}
\fontsize{240}{0}\selectfont
\color{blue!60!black}%
\faSpin{}% 回転!
\end{document}
# sample-6.tex をGIF画像 sample-6.gif に変換する
> perl tcspingif.pl -e xelatex sample-6.tex

f:id:zrbabbler:20200808205725g:plain
sample-6の出力(回転GIF!)

tcspingif.plを使うことで、素敵な「回転ゆきだるま☃」の画像をつくることができました!

おまけ:「点滅☃画像」する話

実は、tcspingif.plはtcfaspinパッケージの他にbxblinkパッケージにも対応しています6。つまり、tcspingif.plを利用すると、「回転ゆきだるま☃」だけでなく「点滅ゆきだるま☃」の画像も生成できます(素敵)。

[sample-7.tex]
% pdfLaTeX文書; UTF-8
\documentclass[margin=25.5bp]{standalone}
\usepackage{xcolor,scsnowman}% ゆきだるま☃!
\usepackage{bxblink}% 点滅!
\begin{document}
\textblink{\scsnowman[scale=40,
  muffler=red,hat=red!75!black,buttons,arms,snow]}%
\end{document}
# sample-7.tex をGIF画像 sample-7.gif に変換する
> perl tcspingif.pl -e pdflatex sample-7.tex

f:id:zrbabbler:20200808222213g:plain
sample-7の出力(点滅GIF!)

イロイロやってみる

某ZR氏のツイッタァーでよく見かけるやつ

「赤マフラーと青マフラーと緑マフラーのやつが並んで回っている」画像をつくってみましょう。基本的なデザインを次のように決めます:

  • 画像のサイズを600×240ピクセルとする。
  • 横に三等分した領域の真ん中にゆきだるま☃を配置する。つまり、(100,120)に赤マフラー、(300,120)に青マフラー、(500,120)に緑マフラーを置く。

描画にはTikZを利用しますが、ここで座標の単位をピクセル(既に述べた通り、これは1bpと同じです)に合わせるために、tikzpicture環境の設定にx=1bp,y=1bpを入れておきます。また、最初のうちはtcfaspinを読み込まずに、「PDFファイルの更新に表示を追随する」機能をもつPDFビューアを用いてゆきだるま☃の位置や大きさを調整するのがよいでしょう。

% pdfLaTeX文書; UTF-8
\documentclass{standalone}
\usepackage{xcolor,scsnowman}% ゆきだるま☃!
\colorlet{mygreen}{green!50!black}
%\usepackage{tcfaspin}% まだ読み込まない
\begin{document}
\begin{tikzpicture}[x=1bp,y=1bp]% 座標を"ピクセル"単位にする
% 画像全体のサイズを600×240ピクセルに設定する
\useasboundingbox (0,0) rectangle (600,240);
% ↓満足するまで試行錯誤して調整する
\node at (100,120) {% 赤マフラー
  \scsnowman[muffler=red,scale=XXX,...]};
\node at (300,120) {% 青マフラー
  \scsnowman[muffler=blue,scale=XXX,...]};
\node at (500,120) {% 緑マフラー
  \scsnowman[muffler=mygreen,scale=XXX,...]};
\end{tikzpicture}
\end{document}

満足する構成が得られたら、tcfaspinを読み込んだ上で、\scsnowmanの出力に\faSpinを適用します。

[sample-8.tex]
% pdfLaTeX文書; UTF-8
\documentclass{standalone}
\usepackage{xcolor,scsnowman}
\colorlet{mygreen}{green!50!black}
\colorlet{mylbrown}{rgb,10:red,7;green,5}
\pagecolor{mygreen!5}
\usepackage{tcfaspin}% 回転!
\begin{document}
\begin{tikzpicture}[x=1bp,y=1bp]
\useasboundingbox (0,0) rectangle (600,240);
\node at (100,120) {% 赤マフラー(ほうき)
  \faSpin{\scsnowman[scale=15,
    hat=red!75!black,muffler=red,
    broom=mylbrown,snow,arms,buttons]}};
\node at (300,120) {% 青マフラー(冷や汗)
  \faSpin{\scsnowman[scale=15,
    hat=blue!75!black,muffler=blue,
    arms,buttons,sweat,mouthshape=tight]}};
\node at (500,120) {% 緑マフラー(♪)
  \faSpin{\scsnowman[scale=15,
    hat=mygreen!75!black,muffler=mygreen,
    note=green!30!black,snow,arms,buttons]}};
\end{tikzpicture}
\end{document}

まずは普通にpdflatexでPDFに変換してAdobe Readerで回転している様子を確かめます。イイカンジだったら、いよいよtcspingifを実行して画像に変換しましょう。

# sample-8.tex をGIF画像 sample-8.gif に変換する
> perl tcspingif.pl -e pdflatex sample-8.tex

f:id:zrbabbler:20200809004753g:plain
sample-8の出力(0.5Hzくらい)

これでもイイカンジですが、某ZR氏によると、ゆきだるま☃の回転速度は「1Hzあたり(1秒で1回転)」がよいらしいです。なので、速度を2倍に上げましょう。

# 回転速度を2倍にする
> perl tcspingif.pl -e pdflatex -b 2 sample-8.tex

f:id:zrbabbler:20200809004831g:plain
sample-8の出力(1Hzくらい)

トッテモ素敵!

どっかのSlackでよく見かけるやつ

「雪だけ点滅しているやつ」の画像をつくってみましょう。次のようにします:

  • 雪つきの\scsnowmanを描いて、それを点滅させる。
  • その後に、全く同じ位置に、雪なしの\scsnowmanを描く。結果的に雪の部分だけ点滅しているように見える。
[sample-9.tex]
% pdfLaTeX文書; UTF-8
\documentclass{standalone}
\usepackage{xcolor,scsnowman}% ゆきだるま☃!
\usepackage{bxblink}
\begin{document}
\begin{tikzpicture}[x=1bp,y=1bp]
\useasboundingbox (0,0) rectangle (360,360);
\node at (180,180) {% 雪つき, 点滅
  \textblink{\strut\scsnowman[scale=40,snow]}};
\node at (180,180) {% 雪なし
  \strut\scsnowman[scale=40,
    muffler=red,hat=red!75!black,buttons,arms]};
\end{tikzpicture}
\end{document}
# sample-9.tex をGIF画像 sample-9.gif に変換する
> perl tcspingif.pl -e pdflatex sample-9.tex

f:id:zrbabbler:20200809004908g:plain
sample-9の出力(素敵!)

やっぱり素敵!

まとめ

というわけで、「せっかくのお盆休みなのに外出自粛のせいで何もやることがない」という人は、自作の「回転ゆきだるま☃画像」を一日中眺めて本質的な「おうち時間」を楽しみましょう! 時には「点滅ゆきだるま☃」もよいかもしれません!


  1. このように「文字を画像として使う」あるいは「画像に文字を入れる」という場合は「和文組版用の調整」は不要(あるいは却って邪魔)であることが多く、その場合、LaTeXエンジンの選択として(u)pLaTeXは避けるのが無難です。日本語処理パッケージを併用せずにpdfLaTeX・XeLaTeX・LuaLaTeXを使用しましょう。OpenTypeフォントを使う場合は、処理時間の点でLuaLaTeXよりもXeLaTeXの方がオススメです。

  2. ImageMagickの古い版では変換用のコマンドはconvertという名前でした。

  3. tcfaspinは内部でanimateパッケージを利用しています。そして、animateパッケージはPDFのスクリプティング機能を利用してページ上のオブジェクトを動的に変化させています。

  4. tcfaspinの\faSpin命令は元来はWebのfontawesomeのfa-spinクラス指定の動作を模倣するものなので、その回転速度に合わせています。

  5. marginの値を縦と横で変えるにはmargin={<横> <縦>}という形で設定しますが、このように{ }を含む指定はクラスオプションでは受け付けられないので、代わりに\standaloneconfigという命令で設定する必要があります。

  6. bxblinkを使用した文書の場合、tcspingifの-tオプションの既定値は8になります。

TeX言語をおすすめできる場合とそうでない場合(私見)

f:id:zrbabbler:20200710213626p:plain

TeX言語をおすすめできる場合

  • TeX言語をやりたい場合

TeX言語をおすすめできない場合

  • それ以外全部

補足

  • もし、不幸にして、TeX言語をやる以外の手段が一切存在しない事態に陥ってしまった場合は、諦めてTeX言語しましょう。

元ネタ