graphicx は画像を入れるためのパッケージだと思われがちですが、名前の x は「拡張」であって「画像」ではありません。実際、このパッケージが持つ \rotatebox・\scalebox・\resizebox・\reflectbox は、箱に入るものなら何でも——一語でも、数式でも、tabular で組んだ表でも——回し、伸ばし、鏡に映します。ただし箱の寸法は素直には動きません。実測すると、10pt の Xg を \rotatebox{-90} で右に倒した箱は 高さ 0pt、深さ 12.50pt——文字がまるごとベースラインの下にぶら下がります。表の見出しを縦にした瞬間に行間が崩れるのは、これが理由です。このページでは LaTeX で文字を 回転・拡大縮小 する命令を、寸法とドライバという二つの落とし穴とともに整理します。
画像専用ではない — graphicx の四つの箱変形
必要なのは \usepackage{graphicx} の一行だけで、これで四つの変形命令が使えるようになります。四つは二組に分かれます——倍率で指定するもの(\scalebox、\reflectbox)と、目標寸法で指定するもの(\resizebox)、そして角度で指定する \rotatebox。\scalebox{0.8}{…} は「元の 0.8 倍」、\resizebox{5cm}{!}{…} は「幅を 5cm に」。どちらを使うかは、手元にあるのが比率か寸法か で決まります。図表を本文幅に合わせたいなら後者、字を少しだけ大きくしたいなら前者です。
| 命令 | 働き | 書式 |
|---|---|---|
\rotatebox | 中身を反時計回りに回す | \rotatebox[origin=c]{45}{...}。角度は度。負なら時計回り |
\scalebox | 倍率で拡大縮小する | \scalebox{2}[1.5]{...}。第二引数は縦倍率(省略可) |
\reflectbox | 左右を反転する | \reflectbox{...}。中身は \scalebox{-1}[1] と同一 |
\resizebox | 指定した仕上がり寸法に合わせる | \resizebox{幅}{高さ}{...}。片方を ! にすると比を保つ |
\rotatebox — 角度は度、正の値で反時計回り
\rotatebox{角度}{中身} は中身を箱に入れ、指定した 角度(度単位)だけ反時計回りに 回します。正の角度で左回り、負の角度で右回り。\rotatebox{90}{...} なら文字が立ち上がり、\rotatebox{-90} なら反対側へ倒れます。度以外の単位で書きたいときは省略可能引数の units= が使えます——units=-360 を渡せば「時計回りの度」、units=6.283185 なら「反時計回りのラジアン」という具合に、一周に相当する数 を書く決まりです。角度の正負を毎回考えるのが面倒なら、この指定を一度だけプリアンブルで包んでおくのが楽です。
This is \rotatebox{45}{slanted text} in a line of prose.
% clockwise degrees instead of the default anticlockwise:
\rotatebox[units=-360]{90}{tipped to the right}ここで、多くの人がつまずく寸法の話をします。回転した箱の幅・高さ・深さは、回転後の見た目の外形 から計算し直されます。10pt の Xg(幅 12.50pt、高さ 6.83pt、深さ 1.94pt)で測ると、\rotatebox{90} の結果は 幅 8.78pt、高さ 12.50pt、深さ 0pt——元の「高さ+深さ」が新しい幅になり、元の幅が新しい高さになりました。\rotatebox{-90} は同じ幅ですが 高さ 0pt、深さ 12.50pt で、箱ぜんぶがベースラインの下に沈みます。\rotatebox{45} に至っては幅 15.05pt・高さ 13.67pt と、縦にも横にも元より大きくなります。回転は行の高さを変える ——これを知っていれば、回転を入れた直後に行間が急に開く現象に驚かずに済みます。
回転の軸 origin= — 角かっこを書いた瞬間に既定が変わる
回転の中心は省略可能引数 [origin=…] で指定します。値は l(左)・r(右)・t(上)・b(下)・B(ベースライン)・c(中央)を一つか二つ組み合わせたもので、origin=lb なら左下、origin=c なら箱の中心が軸になります。ここに 知らないと必ず混乱する仕掛け があります。graphicx.sty を読むと、省略可能引数を 書かなかった ときは回転の中心が (0,0)、すなわち左端かつベースライン——origin=lB と同じ——になり、逆に 何か一つでもキーを書いた瞬間に既定が箱の中心 c に切り替わる のです。実測でも \rotatebox{90}{Xg} と \rotatebox[origin=lB]{90}{Xg} は幅 8.78pt・高さ 12.50pt・深さ 0pt でぴったり一致し、\rotatebox[origin=c]{45} は同じ 45 度でも高さ 9.97pt・深さ 5.08pt と、ベースラインをまたぐ配分になりました。「units= を足しただけなのに位置がずれた」という症状は、たいていこれです。
なお origin= のほかに x= と y= があり、こちらは軸の位置を 長さで直接 指定します。\rotatebox[x=1cm,y=1cm]{90}{...} のように書くと、箱の左下から測った (1cm, 1cm) が回転の中心になります。九つのキーワードでは足りない微調整のときに使う道具です。
% no optional argument: the pivot is the left edge on the baseline (= origin=lB)
\rotatebox{90}{upright}
% ANY key present: the default pivot becomes the box centre (origin=c)
\rotatebox[origin=c]{180}{upside down}
\rotatebox[x=1cm,y=1cm]{90}{pivot given as a length}表の見出しを縦にする — 幅は縮むが、行が沈む
\rotatebox のもっとも実用的な使い道は、列名の長い表の見出しを縦にして幅を稼ぐ ことです。効果は確かに出ます——\begin{tabular}{ll}Header&b\\ c&d\end{tabular} の幅は 60.42pt でしたが、Header を \rotatebox{90}{...} で立てると 36.50pt まで縮みました。ただし代償があります。同じ実測で、表の深さが 9.50pt から 20.73pt へ増えたのです。前節の寸法の話がそのまま効いていて、縦にした見出しは行の下方向へ伸びる。放っておくと見出し行が本文や次の行と重なりかけます。対策は素直で、\rotatebox[origin=c]{90}{...} で軸を中心に移すか、セルを \raisebox で持ち上げるか、あるいは行の高さを \rule{0pt}{高さ} で確保することです。なお、表そのものを紙面に収める方法——横向きページや sidewaystable、幅を宣言する列——は表のページの担当なので、そちらを参照してください。
\begin{tabular}{lrr}
% rotating the pivot to the centre keeps the row from sinking
& \rotatebox[origin=c]{90}{Measured} & \rotatebox[origin=c]{90}{Predicted} \\
\hline
Sample A & 12.4 & 12.1 \\
Sample B & 9.8 & 10.0 \\
\end{tabular}倍率で拡大縮小・鏡映 — \scalebox と \reflectbox
\scalebox{倍率}{中身} は縦横を同じだけ拡大縮小し、形(アスペクト比)を保ちます。\scalebox{2}{...} は 2 倍、\scalebox{0.5}{...} は半分。縦と横を別々に伸ばしたいときは省略可能な第二引数に 縦方向の倍率 を渡し、\scalebox{横倍率}[縦倍率]{中身} と書きます。実測では \scalebox{2} が幅・高さ・深さのすべてを 2 倍にしたのに対し、\scalebox{1}[2] は幅を 12.50pt のまま高さと深さだけを倍にしました。字を細長く/平たくする用途に使えますが、書体の線の太さまで一方向に歪む ので、本文中では控えめに。
倍率には 負の値 も渡せて、その軸方向に反転します。\scalebox{-1}[1]{...} は横倍率 −1・縦倍率 1、つまり左右反転(鏡文字)です。これは頻出なので専用の省略命令があり、graphics.sty の中で \reflectbox は \Gscale@box-1[1] そのもの として定義されています。実測でも両者の箱は幅 12.50pt・高さ 6.83pt・深さ 1.94pt で完全に一致——つまり \reflectbox は \scalebox{-1}[1] の別名にすぎません。回文「Able was I ere I saw Elba」を半分だけ鏡に映してみると、この命令の挙動がひと目で分かります。
\scalebox{2}{bigger}\quad\scalebox{0.5}{smaller}\quad\scalebox{1}[2]{stretched}
% \reflectbox is literally \scalebox{-1}[1]
Able was I \reflectbox{Able was I}目標寸法に合わせる — \resizebox と星付きの \resizebox*
\resizebox{幅}{高さ}{中身} は、中身を 指定した仕上がり寸法 に合わせます。片方に 感嘆符 ! を置くと、そちらは他方から求めた倍率をそのまま使う——つまり縦横比が保たれます。\resizebox{\textwidth}{!}{...} がいちばんよく使われる形です。寸法の引数のなかでは、中身の元の大きさを表す \width・\height・\totalheight・\depth が使えます。実測でも \resizebox{2\width}{!}{Xg} は \scalebox{2}{Xg} と寸分たがわず幅 25.00pt・高さ 13.67pt・深さ 3.89pt になりました。
見落とされがちなのが、\resizebox の高さ引数は「高さ」であって「高さ+深さ」ではない という点です。\resizebox{!}{1cm}{Xg} を測ると高さは 28.46pt(=ほぼ 1cm)ですが、その下にさらに深さ 8.10pt がぶら下がり、箱ぜんぶでは 1cm を超えます。総高さで指定したいときは 星付きの \resizebox* を使います。同じ \resizebox*{!}{1cm}{Xg} の実測は高さ 22.15pt・深さ 6.30pt で、合計 28.45pt——ちょうど 1cm に収まりました。「1cm に縮めたはずが行からはみ出す」ときは、この星の有無を疑ってください。
% twice the original width, aspect ratio kept
\resizebox{2\width}{!}{double width}
% height only vs. height+depth
\resizebox{!}{1cm}{Tall} % height = 1cm, depth hangs below
\resizebox*{!}{1cm}{Tall} % height + depth = 1cm\resizebox のもっとも多い使い道は、本文幅をはみ出す表を丸ごと縮めて収める ことです。tabular 環境ごと \resizebox{\textwidth}{!}{...} で包むだけで幅は必ず収まります。ただしこれは諸刃の剣で、表のなかの文字まで一緒に縮む ため、強く縮めると本文より小さな——ときに判読しづらい——字になり、周囲との字面もそろわなくなります。あとから表のフォントサイズを指定し直しても、最終的に箱ごと縮むので効きません。表がどれだけ縮むか、そして小さすぎる表を渡したときに何倍まで膨らむかは、幅の広い表のページが実測値つきで扱っています。まずは列幅の調整や列の取捨選択で表そのものを幅に収めるのが本筋で、\resizebox は最後の手段と考えるのが無難です。
回転しない — ドライバ指定の食い違い
\rotatebox は TeX が字を回して描くわけではありません。TeX は「ここから先を何度回せ」という指示を出力ファイルに埋め込むだけで、実際に回すのは 後段のドライバ です。だから ドライバの指定を間違えると、エラーも警告も出ないまま回転だけが消えます。実測してみます——\usepackage[dvips]{graphicx} と書いた文書を pdfLaTeX で組むと、コンパイルは正常終了し(エラー 0 件)、しかし出来上がった PDF の内容ストリームには 変換行列 cm が一つも入っていません。文字はまっすぐ並んだままです。同じ文書からドライバ指定を外すと、ログに Package graphics Info: Driver file: pdftex.def と出て、PDF には .70709 .70709 -.70709 .70709 0 0 cm——45 度の余弦と正弦——が現れます。
結論は単純です——ドライバは指定しない。pdfLaTeX・XeLaTeX・LuaLaTeX のいずれも graphicx が自動で判別するので、[dvips] や [pdftex] を手で書くのは、まさに食い違いを作り込む行為です。DVI を経由する場合だけ話が別で、latex で組むと graphicx の既定ドライバは dvips になり、DVI のなかには生の PostScript(ps: gsave currentpoint currentpoint translate 45 neg rotate …)が書き込まれます。dvipdfmx はこの PostScript 特殊命令をある程度解釈できるので実際には回りますが、経路として素直なのは \usepackage[dvipdfmx]{graphicx} を明示することで、そのときは DVI に pdf:btrans rotate 45 という PDF 向けの指示が入ります。DVI がドライバへ何を渡しているかという話そのものは、DVI と PDF の変換を扱うページに詳しくあります。
より高水準な adjustbox — max width= は「縮めるだけ」
graphicx の命令は素朴で強力ですが、組み合わせると入れ子が深くなります。\usepackage{adjustbox} で読み込む adjustbox は、これらを \includegraphics 流の キー=値インターフェース に一本化した高水準の代替です。\adjustbox{angle=45,scale=0.8}{…} のように、回転(angle=)・倍率(scale=)・目標寸法(width=/height=)・鏡映(reflect)を一度に指定でき、同名の adjustbox 環境も使えます。実測では \adjustbox{angle=45}{Xg} の箱が \rotatebox{45}{Xg} と寸分たがわず一致したので、内部でやっていることは同じです。違いは書きやすさと、次に述べる「上限」の考え方にあります。
とくに便利なのが max width=\textwidth(および max totalheight= など)です。前節の \resizebox{\textwidth}{!}{...} は、中身が本文幅より 狭くても拡大してしまいます が、max width= は「はみ出すときだけ縮め、収まっていれば手を付けない」ように作られています。実測でも、一列だけの小さな tabular(幅 17.00pt)は max width=\textwidth を通しても 17.00pt のまま でしたが、同じ表を \resizebox{\textwidth}{!} に渡すと \textwidth いっぱいの 345.00pt まで引き伸ばされました。だから、\includegraphics の癖で全部の表に \resizebox を付けると、狭い表だけが巨大化します。「必要なときだけ縮め、決して拡大しない」を既定にする ——実務ではこれがいちばん事故が少ない選択です。
\usepackage{adjustbox}
% ...
\adjustbox{angle=45,scale=0.8}{rotate and scale in one go}
% shrinks only when the content overflows; leaves narrow tables alone
\adjustbox{max width=\textwidth}{%
\begin{tabular}{lrr} ... \end{tabular}%
}