MetaPost (luamplib, gmp) で☃
これは「TeX & LaTeX Advent Calendar 2018」の 3 日目の記事です.2 日目は puripuri2100 さん,4 日目は golden_lucky さんです.
はじめに
LuaTeX-ja に関わっている関係で,私は LaTeX で文書を作る時はほぼすべて LuaLaTeX を使用しています.
その際に図をどうやって作るか,ということはいつも問題になります.(u)pLaTeX + dvipdfmx を主に使っていたときには 初等数学プリント作成マクロ emath を主に使用していました(今でも周囲にはそういう人がちらほらいます).また,今から始めるというのであれば PGF/TikZ(TeX Wiki 内の記事)を使う,というのがメジャーな選択肢となるのでしょう.
さて,LuaTeX には 内部に MetaPost ライブラリが含まれており,さらにそれを TeX から扱うためのパッケージとして luamplib パッケージというものが制作されています1.これを利用しない手はないではないか……ということで,私は専ら MetaPost を図の作成に用いるようになりました.
luamplib パッケージの使い方
基本的な使い方
基本的には \usepackage
で読み込み,mplibcode 環境内に MetaPost コードを記述するだけです.点につけるラベルなど,TeX コードを記述したい場合は btex ... etex
で囲んだり,textext()
を使ったりします.
\documentclass{article}
\usepackage{luamplib}
\begin{document}
Hello, MetaPost! \vrule
\begin{mplibcode}
beginfig(1);
pickup pencircle scaled 0.25mm;
draw (0,0)..(0,5mm)..(1cm,5mm)..(5mm,0mm)..(-5mm,0)..cycle;
dotlabel.lrt(btex $P_1$ etex, (0,0));
endfig;
\end{mplibcode}
\vrule HOGEHOGE
\end{document}
ラベルに日本語を使いたい場合,LuaTeX-ja パッケージをいつもどおり読み込むだけで問題ありません(LuaTeX-ja 側で何か特別なことをしているのでもありません).
LuaJITTeX 使用時の注意
Lua 5.2/5.3 の代わりに LuaJIT を利用した LuaJITTeX で luamplib パッケージを読み込もうとすると,以下のようなエラーが発生します.これは LuaJITTeX において lfs が定義済みなのになぜか読み込み済みライブラリとしてマークされていないことによるようです.
module 'lfs' not found:
no field package.preload['lfs']
[kpse lua searcher] file not found: 'lfs'
[kpse C searcher] file not found: 'lfs'
stack traceback:
[C]: in function 'require'
...texlive/2018/texmf-dist/tex/luatex/luamplib/luamplib.lua:48: in main chunk
[C]: in function 'require'
[\directlua]:1: in main chunk.
l.22 \directlua{require("luamplib")}
?
どうやら luamplib.lua 中の 48 行目を以下のように書き換えれば良いようです:
local lfs = lfs or require ('lfs') -- 元は local lfs = require ('lfs')
\everymplib
, \everyendmplib
mplibcode 環境内に毎回 beginfig ... endfig
や,図中で使いたい各種マクロを繰り返し書くのは面倒です.luamplib パッケージでは \everymplib
, \everyendmplib
を使って,mplibcode 環境の開始・終了に自動で挿入される MetaPost コードを指定できます.例えば,毎回自動で beginfig
, endfig
を追加させることにし,さらに領域を斜線で塗るマクロ hatch
を入れると次のようになります.
\documentclass{article}
\usepackage{luamplib}
\everymplib{beginfig(1);
def hatch(expr p)=
begingroup
save pct, x, y; picture pct[];
numeric xl, xu, yl, yu;
pct1 := currentpicture; currentpicture := nullpicture;
draw p;
(xl, yl) = llcorner currentpicture; (xu, yu) = urcorner currentpicture;
currentpicture := nullpicture;
pickup pencircle scaled 0.125mm;
for i = xl-xu step 1.5mm until yu-yl:
draw (xl, i+yl)--(xu, i+yl+(xu-xl));
endfor;
clip currentpicture to p;
pct2 := currentpicture; currentpicture := pct1; draw pct2;
endgroup;
enddef;
}
\everyendmplib{endfig;}
\begin{document}
\begin{mplibcode}
path p; p:=(0,0)--(0,5mm)..(1cm,2mm){dir -50}..(5mm,-3cm)--(2cm,0mm)--cycle;
hatch(p); pickup pencircle scaled 0.25mm; draw p;
\end{mplibcode}
\end{document}
寸法・色の指定
mplibcode環境で描かれる図は,周囲の文字色の影響は受けません(無指定時はいつも黒).mplibcode 環境内で寸法や色を指定するには,それぞれ \mpdim
, \mpcolor
命令を使用します.color パッケージや xcolor パッケージを読み込んでいる場合には,\mpcolor
の引数には \color
で指定可能な色指定をそのまま記述できます.xcolor パッケージを読み込んでいると「現在の色」を .
で表現できるので,\mpcolor{.}
を活用することで周囲の文字色と同じ色にすることができます.
\documentclass{article}
\usepackage{luamplib}
\usepackage{xcolor}% 自動では読まない
\begin{document}
M\textcolor{red}{xyz%
\begin{mplibcode}
beginfig(1);
u:=0.5\mpdim{4ex}+2mm; v:=\mpdim{4em};
fill (0,0)--(2v,0)--(2v,u)--cycle ; %無指定時は黒
fill (0,0)--(2v,0)--(2v,.5u)--cycle withcolor \mpcolor{.}; % 周囲の文字色
fill (0,0)--(1v,0)--(0,1u)--cycle withcolor \mpcolor{red!90!black};
fill (0,0)--(.8v,0)--(0,.8u)--cycle withcolor \mpcolor{blue!80!black};
fill (0,0)--(.6v,0)--(0,.6u)--cycle withcolor \mpcolor{green!70!black};
endfig;
\end{mplibcode}
aa}
\end{document}
なお,\mpcolor
で指定した色に対しては withcolor blue+0.5\mpcolor{red!90!black}
のように演算を行うことはできません.
本題:scmpsnowman パッケージ
さて,luamplib パッケージの使い方を紹介するだけでは記事としておもしろくありません.日本の(一部の)TeX ユーザには☃(ゆきだるま)が流行しているので,それを使ってなにかやることにしました.
LaTeX 上でゆきだるまを描く手法として,aminophen さんの scsnowman パッケージ(GitHub リポジトリ,開発者による紹介記事1,紹介記事2)が知られています.このパッケージは TikZ による実装だったので,MetaPost (luamplib) に移植してみました.
- scmpsnowman パッケージ(GitHub リポジトリ)
ネタで作ったものなので,大元の scsnowman パッケージレポジトリの個人フォーク→その中の一ブランチ→さらに下位フォルダ,というひっそりとした箇所においています.
動作環境
想定する環境は TeX Live 2018 上の LuaLaTeX ですが,(u)pLaTeX/pdfLaTeX/XeLaTeX でも動くかもしれません(後述).以下のパッケージが必要です.
- luamplib パッケージ(LuaLaTeX 下のみ),gmp パッケージ(その他)
- xcolor パッケージ
- keyval パッケージ(本家と同様,オプション引数の解釈のため.LuaTeX-ja を使っているならすでに入っている)
- etoolbox パッケージ(LuaTeX-ja を使っているならすでに入っている)
基本的な使い方
まず,scmpsnowman-normal.def, scmpsnowman.sty, scmpsym-base.sty を TeX が参照できるディレクトリに配置しておきます.
LaTeX ソース内からは,通常通り \usepackage
で読み込み,本家 scsnowman パッケージと同様にゆきだるまを置きたい場所で \scsnowman
命令を実行するだけです.
\documentclass{ltjsarticle} % LuaLaTeX 文書
\usepackage{scmpsnowman}
\begin{document}
これはゆきだるま\scsnowman です.
\end{document}
下のサンプルのように,本家と同じ書式で各種オプションを指定できるようにしています.\scsnowman
命令以外の動作確認はほとんどしていません.
\documentclass{ltjsarticle}
\usepackage[svgnames]{xcolor}
\usepackage{scmpsnowman}
\usepackage{mflogo} % MetaPost ロゴ
\scsnowmandefault{hat=Green,arms=Brown,snow=SkyBlue} % デフォルト指定
\begin{document}
\MP で\scsnowman[muffler=Red,,adjustbaseline]を描けます.
\end{document}
(2018-12-04 追記)上記 sample1.tex, sample2.tex では LuaTeX-ja のクラスファイルを使いましたが,その必要はありません.例えば以下の例のように.
\documentclass{minimal}
\usepackage{scmpsnowman}\listfiles
\begin{document}\scsnowman\end{document}
% *File List*
% minimal.cls 2001/05/25 Standard LaTeX minimal class
% scmpsnowman.sty 2018-12-02 Snowman variants using MetaPost
% etoolbox.sty 2018/08/19 v2.5f e-TeX tools for LaTeX (JAW)
% xcolor.sty 2016/05/11 v2.12 LaTeX color extensions (UK)
% color.cfg 2016/01/02 v1.6 sample color configuration
% luatex.def 2018/01/08 v1.0l Graphics/color driver for luatex
% scmpsym-base.sty 2018-12-02 Base for emoji variants using MetaPost
% luamplib.sty 2018/09/27 v2.12.5 mplib package for LuaTeX
% keyval.sty 2014/10/28 v1.15 key=value parser (DPC)
% scmpsnowman-normal.def
% supp-pdf.mkii
% ***********
なお supp-pdf.mkii は luatex.def から読み込まれるようです.(追記ここまで)
非 LuaLaTeX 環境((u)pLaTeX/pdfLaTeX/XeLaTeX)
LuaLaTeX でない環境では,もちろん luamplib パッケージを使うことはできません.その代わりに,同様の「LaTeX ソース中に MetaPost コードを記述する」機能を提供するパッケージの一つに gmp パッケージがあります.scmpsnowman パッケージは,LuaLaTeX でない環境で読み込まれた場合には自動的に gmp パッケージを読み込みます.
gmp パッケージは,mpost 環境の中に書かれた内容を外部ファイルに書き出し,shell-escape が有効なら(パッケージ側にも shellescape オプションを渡す必要があります),その機能を使って MetaPost を実行する,という方式を取っています.shell-escape が無効の場合は sh sample3+mp.sh
などとしてあとから自分で MetaPost 実行(など)を行うシェルスクリプトを自分で実行する必要があります.
ということで,LuaLaTeX でない環境下で scmpsnowman パッケージを使う場合には以下のようなソースを記述することになります.しかし shell-escape を有効にするのはセキュリティ的によろしくないので,非 LuaLaTeX 環境下では MetaPost をわざわざ使う意味は薄いように思います.☃☃☃おとなしく本家 scsnowman パッケージを使いましょう☃☃☃
%#! ptex2pdf -l -ot '-shell-escape' sample3.tex
\documentclass[dvipdfmx]{minimal}
\usepackage[shellescape]{gmp}
\usepackage{scmpsnowman}
\begin{document}
This is a snowman:
\scsnowman[adjustbaseline,scale=2,hat,muffler=red,arms=blue]
\end{document}
gmp パッケージ下での色の指定
gmp パッケージでは \mpdim
命令で TeX の寸法を指定することができます2が,\mpcolor
に対応する命令はありません.そこで,scmpsnowman パッケージ中では,luamplib の実装と似た(?)感じで適当に実装しています.
luamplib の \mpcolor
命令を使うと,withcolor \mpcolor{blue}
は最終的には次の形になるようです(しっかり確かめたわけではありませんが):
withcolor 1 withprescript "MPlibOverrideColor=0 0 1 rg 0 0 1 RG"
LuaTeX 内蔵の MetaPost ライブラリでなく,本来の MetaPost ソースで同じような指定を考えてみます.
beginfig(1);
draw (0,0)--(1,0) withcolor 1 withprescript "0 0 1 setrgbcolor";
draw (0,0)--(2,0) withcolor 1 withprescript "0 0 1 setrgbcolor";
endfig;
end.
上の a.mp を MetaPost に処理させると,次のような PostScript ファイル a.1 が出来上がります.withprescript
による色指定の後に,withcolor 1
による 1 setgray
が来てしまい,結果として最初のパスにおける withprescript
による色指定は無効になってしまいます.
%!PS
% (省略)
%%Page: 1 1
0 0 1 setrgbcolor
1 setgray 0 0.5 dtransform truncate idtransform setlinewidth pop [] 0 setdash
1 setlinecap 1 setlinejoin 10 setmiterlimit
newpath 0 0 moveto
1 0 lineto stroke
0 0 1 setrgbcolor
newpath 0 0 moveto
2 0 lineto stroke
showpage
%%EOF
そのため,gmp パッケージを使う際には,パスの色指定のところで withoutcolor \mpcolor{blue}
のように記述(\mpcolor
は withprescript ...
に最終的に展開)するようにしています3.
-
もとは ConTeXt 中のコードを plain TeX や LaTeX でも扱えるように変更を加えたものだそうです. ↩
-
実は,gmp パッケージが
\mpdim
命令を先に実装し,luamplib パッケージがそれに触発されて\mpdim
命令を追加したという順番です. ↩ -
xcolor パッケージの色指定から PostScript 形式の指定への変換では,dvips.def, dvipdfmx.def, xetex.def にある
\c@lor@to@ps
命令を使って行っています.しかし pdftex.def にはこの命令がないので,PDF における色指定を PostScript 形式のそれに変換する処理を scmpsym-base.sty 中に適当に作りました. ↩
Author And Source
この問題について(MetaPost (luamplib, gmp) で☃), 我々は、より多くの情報をここで見つけました https://qiita.com/h-kitagawa/items/4765b3f4593d67a2d4d3著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .