LaTeX: graphicx と color の危険な関係

## 前提

  * LaTeX文書をdvipdfmxを使ってPDF文書に変換している。
  * graphicx（または graphics）パッケージを利用している。
  * colorパッケージを利用している。または何かのパッケージが内部でcolorパッケージを読み込んでいる可能性がある。

## 問題

  * graphicxパッケージの挙動が不正になる（例えばEPS画像の位置がずれる、出力されない）ことがある。
  * 原因を調べた結果、graphicxパッケージのドライバ指定が間違っていること[（参考）](http://qiita.com/zr_tex8r/items/089b56291588f7b05b02)に気付いた。
  * そこで、graphicxパッケージに `dvipdfmx` オプションを追加する**対処を行ったが、挙動が変わらない。**

## 対策方法

colorパッケージにも `dvipdfmx` オプションを効かせる必要がある。そのため、パッケージではなく、**文書クラス指定**（`\documentclass`）のオプションにおいて `dvipdfmx` を指定する。これで、colorやgraphicx、および他のほぼ全てのパッケージについて、`dvipdfmx` オプションが（有効であれば）適用される。

※<ins>[2021-01-26追記]</ins> TeX Live 2020以降では「（DVI出力の場合は）**文書クラスで常にドライバオプション**（dvipdfmxなど）**を指定する**ことが推奨されるようになった。

```latex
\documentclass[a4paper,dvipdfmx]{jsarticle}% ここで指定
%......
\usepackage{graophicx}% dvipdfmx は自動的に有効になる
%.....
\usepackage{color}% dvipdfmx は自動的に有効になる
```

#### 補足

本記事の昔の版では、上記の方法のほかに、「colorパッケージにも `dvipdfmx` を追加する」という方法を紹介していた。

```latex:(非推奨)
\documentclass[a4paper]{jsarticle}
%......
\usepackage[dvipdfmx]{graophicx}% これは対処した
%.....
\usepackage[dvipdfmx]{color}% ここにも dvipdfmx を入れる
```

しかし、「graphicxやcolorを内部で読み込むパッケージ」を利用している場合は、この方法では失敗する（`Option clash` のエラーが発生する、結局不正なドライバが使われる、等）可能性がある。文書クラスでドライバ指定を行う方法の方が安全であるため、そちらの方法を推奨する。

## 詳細

※以下では、「**dvipdfmxを利用している**こと」「文書クラスでドライバオプションを指定していないこと」を仮定する。

### colorパッケージも「ドライバ依存」である

graphicxパッケージが「ドライバに依存」することは有名であるが、実は **colorパッケージもドライバに依存する。**

```tex:例1
% dvipdfmx を利用するならドライバ指定が必要
\usepackage[dvipdfmx]{color}
```

多くのTeX配布では、DVI出力の場合のドライバの既定値は `dvips` となっている。なので、以下の記述は**不正である**。

```tex:例2(不正)
% dvipdfmx を使うのに...
\usepackage{color}% ドライバは既定値の dvips
```

ところが現状では、colorパッケージについては、`dvips` ドライバを指定してもdvipdfmxでの動作には表面上の問題が全く起こらない。このため、colorのドライバ指定については無頓着なユーザも多いと思われる。
※「実際には問題ない」ことを利用して敢えて「不正なドライバ」を指定するという**バッドノウハウ**が行われることもありえるが、ここではそれは措いておく。

### graphicxとcolorはドライバを「共有」している

ところが、colorとgraphicxを同時に使うと話が複雑になる。

```tex:例3(不正)
% dvipdfmx なのか dvips なのか、はっきりしろ！
\usepackage[dvipdfmx]{graphicx}% ドライバは dvipdfmx
\usepackage{color}% ドライバは既定値の dvips
```

ここではドライバ指定が不正（`dvips`）なのはcolorパッケージなので、普通に考えるとcolorパッケージの命令の動作が不正になりそうである。しかし、前述の通り、実際にはそこでは問題は起こらない。その代わりに、正しいドライバ指定（`dvipdfmx`）であるはずのgraphicxパッケージの命令（`\includegraphics` 等）の動作が不正になる、という不可解な現象が起こってしまう。

その理由は、colorとgraphicxの両パッケージの実装にある。

例1のソースコードを実行すると、LaTeXは以下のように動作する。

  * まず、colorパッケージのプログラムが書かれたファイル（color.sty）を読み込む。
  * 次に、colorパッケージの「dvipdfmxに依存する部分」のプログラム（これが「dvipdfmx用のドライバ」である）が書かれたファイル（dvipdfmx.def）を読み込む。

ところが実は、「colorパッケージのdvipdfmx用ドライバ」が書かれたファイル dvipdfmx.def には「graphicxパッケージのdvipdfmx用ドライバ」のプログラムも一緒に書かれているのである。すなわち、例えば `\usepackage[dvipdfmx]{graphicx}` が実行される際は、graphicx.sty（と graphics.sty）の他に、この dvipdfmx.def というファイルが読み込まれる。この事情は他のDVIウェアのドライバについても同じで、要するに**graphicxとcolorはドライバを共用している**のである。

この結果、例3のようなソースコードを実行すると以下のような不可解な結果になるのである。

  * graphicxパッケージのプログラムのファイル（graphicx.sty, graphics.sty）を読み込む。
  * 「graphicx + color共用のdvipdfmx用ドライバ」のファイル（dvipdfmx.def）を読み込む。
  * colorパッケージのプログラムのファイル（color.sty）を読み込む。
  * 「graphicx + color共用のdvips用ドライバ」のファイル（dvips.def）を読み込む。
  * その結果、graphicxのドライバ依存コードもdvips用のもので上書きされてしまうので、graphicxパッケージがあたかも `dvips` オプションを指定した時のような動作をする。これはdvipdfmxを用いている場合は不正な出力になる。
  * 一方、colorはdvips用ドライバでも（表面上は）問題なく動作する。

もちろん、元々が「不正なコード」であるのでその動作は「未定義」であり何が起こっても文句は言えないのだが、実際にこの現象が起きてしまうとその原因を突き止めるのは困難である。

普段から、**パッケージのドライバ指定に十分気を付ける**ことを心掛けたい。