本記事では、DVIをSVGに変換するソフトウェアのdvisvgmについて、「(u)pLaTeXと併用する場合の注意点」について解説します。あわせて、(u)pLaTeX以外も含めて「日本語を含む文書に対してdvisvgmを使う場合の注意点」についても扱います。
前提知識
- dvisvgmの最低限の使い方の知識。
- フツーのLaTeXの知識。
- DVIドライバとは何かを知っている。
- 主題の(u)pLaTeXの節については、フツーの(u)pLaTeXの知識。
dvisvgmのキホンを復習する話
本記事の主題は「(u)pLaTeXでdvisvgmする話」ですが、記事中で紹介する方法を実践する際に前提となるキホンの知識について復習しておきます。
ごくフツーにdvisvgmする話
dvisvgmは「DVIをSVGにする」ソフトウェアであるため、併用する(La)TeXエンジンとしては「PDFを出力するもの(pdfLaTeX等)」ではなく「DVIを出力するもの(欧文LaTeX等)」を選ぶ必要があります。さらにイマドキ(2020年以降)のLaTeXではDVIドライバのオプション(ドライバオプション)を常にグローバルオプションとして指定することが必須になっています。従って、例えば「欧文LaTeX(latexコマンド)とdvisvgmの組み合わせ」用のLaTeX文書の基本形は以下のようになります。
% 欧文LaTeX+dvisvgm
%↓グローバルオプションに'dvisvgm'を指定する(必須!)
\documentclass[dvisvgm]{article}
\pagestyle{empty}% ページ番号不要
\begin{document}
Hello, {\TeX} world!
\end{document}
このLaTeXソースからSVG画像に変換する手順は以下の通りです。
latex example1.tex
dvisvgm --font-format=woff2 example1.dvi
ここで--font-format=woff2は文書中のフォントの埋込形式を指示するものです。(フォントの扱いについては後述。)
XeLaTeXとかLuaLaTeXとかする話
XeTeXは普通は「PDFを直接出力するエンジン」と見なされますが、実はDVIファイル(厳密には拡張DVI形式というもので、ファイル拡張子は.xdv)の出力も可能です。そして、dvisvgmは拡張DVI形式にも対応しているため、XeLaTeXの出力をSVG画像に変換できます。
この手順は「XeTeXの通常の出力(ただし拡張DVI形式)をdvisvgmに入力する」という扱いなので、ドライバ指定は普通のXeLaTeXと同じ、すなわちドライバオプションは無指定にします。
% XeLaTeX(拡張DVI出力)+dvisvgm
\documentclass{article}% ドライバオプション無指定
\usepackage{metalogo}% '\XeTeX'ロゴしたい
\usepackage{fontspec}
\setmainfont{NewComputerModern10}% キリル文字したい
\newfontfamily\fJa{Harano Aji Mincho}% 日本語したい
\pagestyle{empty}
\begin{document}
Привіт, {\XeTeX} \fJa{世界}!
\end{document}
XeLaTeXの出力形式をDVIファイルに切り替えるにはオプション--no-pdfを指定します。ここで出力されるファイル(拡張子.xdv)をdvisvgmに入力します。
xelatex --no-pdf example2.tex
dvisvgm --font-format=woff2 example2.xdv
さらに、LuaTeXもDVIファイルを出力するモードを備えていて、dvilualatexというコマンドで「DVI出力のLuaLaTeX」を起動できます。dvisvgmはこのdvilualatexの出力のDVI形式にも対応していて、dvilualatex+dvisvgmの組み合わせは実用もされているようです。ただしdvilualatexは通常のLuaLaTeXとは別のエンジンという扱いになるため、これをサポートしているパッケージが乏しいという難点があります。
LaTeXの枠組ではdvilualatexは「DVI出力のエンジン」の一種と見なされるので、通常のDVI出力と同様にドライバ指定を行う必要があります。従って、今の場合はdvisvgmのドライバオプションを指定します。
% LuaLaTeX(DVI出力)+dvisvgm
\documentclass[dvisvgm]{article}% ドライバはdvisvgm
\usepackage{fontspec}
\setmainfont{NewComputerModern10}% アルメニア文字したい
\newfontfamily\fKo{Un Batang}% ハングルしたい
\pagestyle{empty}
\begin{document}
Բարև, {Lua\TeX} \fKo{세상}!
\end{document}
変換手順は他の一般的なDVI出力エンジンの場合と同じです。
dvilualatex example3.tex
dvisvgm --font-format=woff2 example3.dvi
フォントの取扱の話
先の例でdvisvgmの--font-formatオプションを使いましたが、ここでフォントの取扱を指定するオプションについてまとめておきます。
-
--font-format=‹形式›: フォントデータを(CSSを介して)出力ファイルに埋め込む。‹形式›にはwoff2(WOFF2形式)、woff(WOFF形式)、ttf(TrueType形式)が指定可能。
今のWebブラウザは高効率のWOFF2形式に対応しているのでwoff2の指定が最適です。ただし古い版のdvisvgmではwoff2が未サポートの場合があり、この場合は代わりにwoffを指定します。
フォントデータを埋め込む代わりにフォントをアウトライン化する扱いも可能です。
-
--no-font: フォントをアウトライン化して、文字を単なる図形の一種として扱う。
フォントを--font-formatで埋め込んだ場合は文字データが保持される(例えばWebページ上で検索可能になる)のに対して、--no-fontでアウトライン化した場合は文字データは消滅します。
--font-formatと--no-fontのどちらも指定しない既定の状態では、dvisvgmはフォントデータをCSSではなく「SVGフォント」という機構を用いて埋め込みますが、この「SVGフォント」の仕様は現在では非推奨となっていて大半のソフトウェアはこれをサポートしていません。
出力対象の領域の話
dvisvgmの主要な使い方が「単一の図や数式からなる画像」を作ることであるため、既定ではDVIの「先頭ページに実際に描画されたものを囲む最小の矩形の領域」の部分のみが画像として出力されます。今まで挙げた例1でも文字の部分のみからなる余白のない画像が出力されていました。
出力対象の領域を変えるには--bboxオプションを使います。
-
--bbox=‹指定›: 出力対象の領域を指定する。‹指定›は以下のものが使える:-
min:(既定) 「最小の矩形の領域」とする。 -
‹長さ›: 「最小の矩形の領域」の周りに‹長さ›分の余白を入れる。 -
‹x1›,‹y1›,‹x2›,‹y2›: DVI座標系で (x1, y1) と (x2, y2) を対角線とする矩形とする。
※コンマ区切りで長さ値を4つ指定する。 -
papersize: TeX側での出力用紙サイズ設定2に従う。 -
‹用紙サイズ名›: (TeXの通常の慣習3の下で)その用紙サイズの縦置きに相当する領域を指定する。 -
‹用紙サイズ名›-l4: その用紙サイズの横置きに相当する領域を指定する。
※‹用紙サイズ名›の有効な値には例えばa‹番号›(A判)、b‹番号›(ISO B判)、letter(レター)・legal(リーガル)がある。JIS B判を表す名前は用意されていない。
-
※「長さ値」はTeXの長さ表記(1cmや20bp等)で指定する。
LaTeXで画像を作るのにはstandaloneクラスが便利ですが、このクラスを用いると「TeXの側で用紙サイズを設定する」ことになるため、dvisvgmと併用する場合--bbox=papersizeを指定する必要があります。standaloneで
の画像を作る例を挙げます。
% 欧文LaTeX+dvisvgm
\documentclass[dvisvgm]{standalone}
\usepackage{scsnowman}% ゆきだるま😊
\usepackage[svgnames]{xcolor}
\setlength{\unitlength}{1bp}% bp=SVGでの'pt'
\begin{document}%
% pictureでの指定(240bp×180bp)が外形のサイズになる
\begin{picture}(240,180)
\put(120,90){\makebox(0,0)[c]{%
% 赤マフラーの☃️を描く(素敵😊)
\scsnowman[scale=20, muffler=Red, hat=Green,
buttons=RoyalBlue, arms=Brown, snow=SkyBlue]}}
\end{picture}%
\end{document}
latex example4.tex
dvisvgm --bbox=papersize example4.dvi
の左右の余白を含めて正しいサイズで出力されました(素敵
)
もし「通常のレイアウトの文書をPDFではなくSVGとして出力したい」という場合は、--bbox=papersizeの指定の他に出力ページ指定も必要です。
-
--page=‹ページ番号列›: 出力対象となるDVIのページ番号を指定する。既定値は“1”。
※1-2,4,8,10-のような形式で指定する(-で全ページ)。
既定では先頭ページしか対象にならないので、複数ページの文書の場合は--page=-の指定が必要になります。
% 欧文LaTeX+dvisvgm
\documentclass[dvisvgm,a5paper]{article}
\usepackage{bxpapersize}% 出力用紙サイズを記録したい
\usepackage{lipsum}% '\lipsum'したい
% 標題を設定する
\title{Non-essential Document}
\author{Non-ZR}
\date{Non-today}
\begin{document}
\maketitle
\section{The dummy text}
\lipsum[1-6] % Lipsumのダミーテキスト
\end{document}
latex example5.tex
dvisvgm --font-format=woff2 --bbox=papersize --page=- example5.dvi
example5.texは3ページの文書であるため、example5-1.svg、example5-2.svg、example5-3.svgの3つのSVGファイルが出力されます。
日本語だが(u)pLaTeXしない話
主題の「dvisvgmで(u)pLaTeXする方法」に入りたいところですが、その前に一つ注意をしておきます。それは「LaTeXで日本語を出力するのに必ずしも(u)pLaTeXを使う必要はない」ということです。
(u)pLaTeXを使うと日本語の文字をただ出力できるだけでなく、日本語組版の規則に従った “マトモな” 出力ができます。しかしdvisvgmを使うような場面ではマトモな出力が不要なことも多いでしょう。既にexample2.texで「日本語文字を含む例」が現れていることから解るように、XeLaTeXやLuaLaTeXを使えば「日本語文字を含むSVG画像」を簡単にdvisvgmで作成できます。日本語の文字も単なるUnicodeの文字の一種に過ぎないので、特に日本語のための特別な設定は不要です。
% XeLaTeX(拡張DVI出力)+dvisvgm
\documentclass{standalone}
\usepackage[svgnames]{xcolor}
\usepackage{fontspec}
\setmainfont{HaranoAjiGothic-Heavy.otf}
\setlength{\unitlength}{1bp}
\pagecolor{DarkGreen}% 背景色
\begin{document}%
\begin{picture}(100,40)
\put(50,20){\makebox(0,0)[c]{%
\color{Yellow}\fontsize{30}{0}\selectfont
素敵}}
\end{picture}%
\end{document}
xelatex --no-pdf example6.tex
dvisvgm --font-format=woff2 --bbox=papersize example6.xdv
もちろんこの方法では日本語組版規則は適用されないので、約物を含む語句を出力するとマトモでない結果になってしまいます。
% XeLaTeX(拡張DVI出力)+dvisvgm
\documentclass{standalone}
\usepackage[svgnames]{xcolor}
\usepackage{fontspec}
\setmainfont{HaranoAjiGothic-Heavy.otf}
\setlength{\unitlength}{1bp}
\pagecolor{DarkGreen}
\begin{document}%
\begin{picture}(300,40)
\put(150,20){\makebox(0,0)[c]{%
\color{Yellow}\fontsize{30}{0}\selectfont
{\TeX}言語、「素敵」。}}% 約物を含む語句
\end{picture}%
\end{document}
※変換手順はexample6.texと同様。
XeLaTeXの場合はbxjsclsパッケージの文書クラス(bxjsarticle等)を使うことで日本語組版が(ある程度)改善できます。XeLaTeXとbxjsclsの組み合わせはdvisvgmでも動作するので、bxjsarticleクラスを使う5ことでチョットマトモな出力が得られます。
standaloneクラスのclassオプションキーで「基となる文書クラス」を指定できます。つまりclass=bxjsarticleと指定すれば、bxjsarticleクラスの組版設定が適用された状態でstandaloneクラスの処理が有効になります。
% XeLaTeX(拡張DVI出力)+dvisvgm
\documentclass[
class=bxjsarticle, % bxjsarticleを基にする
xelatex, ja=standard, % bxjsarticleのオプション
]{standalone}
\usepackage[svgnames]{xcolor}
\usepackage{fontspec}
\setCJKmainfont{HaranoAjiGothic-Heavy.otf}
\setmainfont{HaranoAjiGothic-Heavy.otf}
\setlength{\unitlength}{1bp}
\pagecolor{DarkGreen}
\begin{document}%
\begin{picture}(300,40)
\put(150,20){\makebox(0,0)[c]{%
\color{Yellow}\fontsize{30}{0}\selectfont
{\TeX}言語、「素敵」。%
\hspace{-.5\zw}}}% '\<'が無効なので手動で調整する
\end{picture}%
\end{document}
そのままでは句点。の後ろの半角空きが残存するため左右のバランスが悪くなります。本来なら\<で空きを除去できるはずですが、現状のbxjsclsでは未実装
なので、\hspace{-.5\xw}で対処しました。
※変換手順はexample6.texと同様。
先述の通り、dvisvgmは「DVI出力のLuaLaTeX(dvilualatex)」にも対応していました。となると「LuaTeXj-jaを使えば完全にマトモな日本語出力が得られるのでは?」と考えたくなるところです。しかし残念ながら、現状のLuaTeX-jaパッケージはdvilualatexをサポートしていません。luatexjaを読み込もうとすると以下のようなエラーが出ます。
! Package luatexja Error: DVI output is not supported in LuaTeX-ja.
See the luatexja package documentation for explanation.
Type H <return> for immediate help.
l.184 }
従って現時点では、完全にマトモな日本語組版をdvisvgmで得る選択肢は(u)pLaTeXの使用に限られます(ざんねん
)
本当に(u)pLaTeXする話
これ以降の話はTeX Liveを前提にします。
いよいよ本題に入ります。といっても、dvisvgmは(u)pTeXの出力する和文拡張版のDVIも公式にサポートしているので、LaTeXソースの書き方についてはこれまでに述べた点に注意すれば十分です。しかし、(u)pTeX特有の「和文フォント」の扱いについて追加で注意すべき点があります。
- 和文用のフォントマップの読込。
- 和文フォントの扱いに関する不具合の回避。
和文のフォントマップを読み込みたい話
レガシーな(XeTeX・LuaTeX以外の)TeXではフォントをTFM(という形式のファイル)で取り扱い、DVIドライバは「TFMと実物のフォントの対応」のデータである「フォントマップ」を利用して対応を把握します。TeX Liveではフォントマップの扱いがupdmapという仕組により一元化されていて、全てのDVIドライバが同じフォントマップのデータを参照します。つまりあるTFMの取扱がdvipdfmxで成功するならdvisvgmでも成功するはずです。
ところが、(u)pTeX特有の「和文フォント」(和文TFM)については少し話が異なります。和文TFMは普通(つまり欧文)のTFMとは扱い方が異なり、その他の事情もあって、和文用のフォントマップは欧文用とは別のkanjix.mapというファイルに格納されます。そしてこのkanjix.mapはdvipdfmxは既定で読み込みますが、dvisvgmは読み込みません。結果的に、dvisvgmは既定状態では(u)pTeXの和文フォントを正常に取り扱えないことになるわけです。
例えば以下のような単純なpLaTeX文書を、いつも通りの手順でSVGに変換してみます。
% pLaTeX+dvisvgm
\documentclass[dvisvgm]{jsarticle}
\pagestyle{empty}
\begin{document}
{\TeX}言語、例によって、「素敵」。
\end{document}
platex example9.tex
dvisvgm --font-format=woff2 example9.dvi
すると、dvisvgmの実行中に以下の警告が出ます。これは和文TFM(rml)のフォントマップが見つからないことを意味しています。
WARNING: no font file found for 'rml'
そして出力された画像は以下のように日本語部分が文字化けしています。
この問題の解決方法は簡単で、「dvisvgmにkanjix.mapを読み込ませる」といいわけです。dvisvgmには追加でフォントマップを読み込むためのオプション--fontmapがあるので、--fontmap=kanjix.mapを指定します。
platex example9.tex
dvisvgm --fontmap=kanjix.map --font-format=woff2 example9.dvi
これで警告が消えて、変換結果が正常になりました。
結局upLaTeXできない話
pLaTeXでの変換が首尾よく成功したので、今度はupLaTeXを試してみましょう。以下の文書を用意します。
% upLaTeX+dvisvgm
\documentclass[uplatex,dvisvgm]{jsarticle}
\pagestyle{empty}
\begin{document}
{\TeX}言語、例によって、「素敵」。
\end{document}
これを--fontmap=kanjix.map付きで変換するのですが、まずは--no-font(フォントをアウトライン化)を試してみます。
uplatex example10.tex
dvisvgm --fontmap=kanjix.map --no-font example10.dvi
これは成功しました。それでは--font-formatでフォントを埋め込んだ場合はどうでしょうか。
uplatex example10.tex
dvisvgm --fontmap=kanjix.map --font-format=woff2 example10.dvi
文字の配置がメチャクチャになってしまいました6。何が起こったのでしょうか。「文字自体は正しいものが出力されていて、位置だけがおかしい」「--no-fontでは正常なのに--font-format=wof2では異常であり、両者で他の設定を変えるべき理由がない」という状況を考慮すると、これはdvisvgmの側の不具合の可能性が高そうです。
この“謎の不具合”が厄介なのは「どういう設定にすれば正常に動作するのか」の判断が難しいことです。以下のような複数の要因が関わってきます。
- エンジンがpLaTeXかupLaTeXか。
- アウトライン化(
--no-font)かデータ埋込(--font-format=woff2)か。 - 実物フォントの種別(TTF/CFF)は何か。
- フォントマップのエンコーディング指定がどうなっているか。
しかも後半2つの項目については、一般のユーザが状況を把握すること自体が困難7でしょう。
自分が実験した範囲に限れば、pLaTeXはよくサポートされている模様で、pLaTeXを使った場合は他の状態の如何にかかわらず正常8な出力が得られました。従って現状では、もし(u)pTeX系の和文を扱うのであれば、敢えてupLaTeXではなくpLaTeXを使うのが安全策なのかも知れません![]()
新しいpxchfonでupLaTeXできる話
実験でもう一つ判ったことは「フォントマップのエンコーディングをunicodeにした(この言葉の意味の解説は割愛します
)場合も安定して正常な出力が得られる」ということです。LaTeXで「エンコーディングをunicodeにする」という指定はpxchfonパッケージを利用すると行えますが、一般のユーザがこの辺りの事情を把握して自分で適切な設定を適用するのは難しいでしょう。そこで、pxchfonを改修して「ドライバ指定がdvisvgmの場合は自動的にエンコーディングをunicodeに切り替える」という機能を追加しました。
最新のTeX Liveでは既に新版が利用可能です。
早速新しいpxchfon(2.3版以降)を使用してみます。ここで大事なのは「pxchfonは読み込むだけでは何も起こらないので、必ずフォント設定を行う必要がある」ことです。今のTeX Liveで既定の和文フォントである「原ノ味フォント」を使う場合でもharanoajiのプリセットオプションの指定が必要です。(これにより「エンコーディングをunicodeにする」指定が適用されます。)
% upLaTeX+dvisvgm
\documentclass[uplatex,dvisvgm]{jsarticle}% ドライバ指定を忘れずに
\usepackage[haranoaji]{pxchfon}% プリセットオプションが必要
\pagestyle{empty}
\begin{document}
ゆきだるま☃、当然、「素敵」。
\end{document}
変換手順に関する注意点として、pxchfonを使う場合には通常時とは異なり--fontmap=kanjix.mapは付けてはいけません。
この理由は、pxchfonを利用する場合はDVI文書中でフォントマップを指定する形になるからです。dvipdfmxとは異なり、dvisvgmでは「一度登録されたフォントマップ指定を文書中の処理で変更する9」ことができません。
uplatex example11.tex
dvisvgm --font-format=woff2 example11.dvi
今度は「IPAexフォント10」を使ってみましょう。pxchfonのプリセットオプションをipaexに変えるだけです。
% upLaTeX+dvisvgm
\documentclass[uplatex,dvisvgm]{jsarticle}
\usepackage[ipaex]{pxchfon}
\pagestyle{empty}
\begin{document}
ゆきだるま☃、当然、「素敵」。
\end{document}
※変換手順はexample11.texと同様。
最後にstandaloneクラスで和文フォントを含めた例を挙げておきましょう。
個の例では\setminchofontで直接フォントを指定していて、しかも和文としてはそのフォントしか使っていないわけですが、それでも何らかのプリセットを指定する必要11があります。
% upLaTeX+dvisvgm
\documentclass[class=jsarticle, uplatex]{standalone}
\usepackage[svgnames]{xcolor}
\usepackage[haranoaji]{pxchfon}
\setminchofont{HaranoAjiGothic-Heavy.otf}
\setlength{\unitlength}{1bp}
\pagecolor{DarkGreen}
\begin{document}%
\begin{picture}(300,40)
\put(150,20){\makebox(0,0)[c]{%
\color{Yellow}\fontsize{30}{0}\selectfont
{ゆきだるま☃、「素敵」。\<}}}% 今度は'\<'が使える
\end{picture}%
\end{document}
uplatex example13.tex
dvisvgm --no-font --bbox=papersize example13.dvi
素敵![]()
補足:古いpxchfonしかない場合
もし2.3版以降のpxchfonが使えなくても、pxchfonの2.0~2.2版が使えるなら代替策があります。pxchfonのオプションにunicode=simpleとlegacycode-replaceを追加すると実質的に「dvisvgmドライバでの新しいpxchfon」と同じ動作になります。
% upLaTeX+dvisvgm
\documentclass[uplatex,dvisvgm]{jsarticle}
\usepackage[haranoaji,unicode=simple,legacycode-replace]{pxchfon}
\pagestyle{empty}
\begin{document}
ゆきだるま☃、当然、「素敵」。
\end{document}
※変換手順と出力結果はexample11.texと同様。
でも指定方法が全く直感的でないので、やはり新しいpxchfonの方がいいですね![]()
まとめ
現時点で、dvisvgmを(u)pLaTeXと併用する場合に特に注意すべき点は以下のようになります。
- pLaTeXでは通常の文書ソースの書き方でよい。
- ただしdvisvgmの実行時に
--fontmap=kanjix.mapオプションが必要。
- ただしdvisvgmの実行時に
- 最新のpxchfonパッケージを併用するとupLaTeXでも使える。
- 必ず何らかのプリセットを使用する。
- この場合はdvisvgmの
--fontmap=kanjix.mapオプションは不要。
-
articleクラスの既定ではページ下部にページ番号「1」が出力されます。これを残しておくとこの「1」も画像に含まれて縦に長い画像になってしまうので、例では
\pagestyle命令でページ番号を消しています。 ↩ -
つまり、DVI中に出力された“papersize special”のことです。 ↩
-
つまり、DVI差表の (−1in, −1in) の点を左上として指定のサイズの領域をとります。例えば、
a4(A4縦)は-25.4mm,-25.4mm,184.6mm,271.6mmという指定と等価になります。 ↩ -
lは“landscape”の略です。略さずに‹用紙サイズ名›-landscapeとも書けます。 ↩ -
もちろん、standalone併用ではなく「通常のレイアウト」の文書クラスとしてもbxjsarticleを使えます。 ↩
-
変換対象領域については正常な出力の「最小の矩形の領域」が採用されるため“上に乗った部分”は実際には画像の外にはみ出てしまいます。説明の便宜のため、前掲の画像では余白を増やして出力したものを使いました。 ↩
-
従って、本記事ではこれらの事項の詳細の解説は割愛します
↩ -
ただしJIS2000字形(CMap
H)とJIS2004字形(CMap2004-H)の区別については、たとえdvipdfmxでは区別が反映される状況においてもdvisvgmでは反映されず、常にフォントの既定の字形が使われるようでした。恐らく「Adobe-Japan1のCIDではなくUnicodeでグリフにアクセスする」処理になっているものだと思われます
↩ -
文書中の処理では新たな登録のみが可能です。また、フォントマップファイルの読込の時点(文書処理開始前)では変更も可能です。 ↩
-
「原ノ味フォント」はAdobe-Japan1対応のCFFグリフのフォント、「IPAexフォント」はTTFグリフのフォントで、両者でフォント形式が異なります。先ほどのpxchfonを使わずにupLaTeXでタイプセットした例で、既定の「原ノ味フォント」では
--no-font指定は正常出力でしたが、TTFグリフの「IPAexフォント」では--no-font指定でも文字化けになります。pxchfonを併用すればどんなフォントでも使えるわけです。ちなみに「Noto CJKフォント」などの「Identity0なフォント」でも大丈夫です。 ↩ -
実は厳密には「プリセットが必要」ではなくて「全てのファミリ・ウェイトについてフォントを指定する」ことが要求される(これを満たしていないと警告が出る)のですが、ヤヤコシイので「プリセットが必要」と考えておくほうが得策です。 ↩














