summaryrefslogtreecommitdiff
path: root/macros/luatex/generic/luamplib
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/luatex/generic/luamplib
Initial commit
Diffstat (limited to 'macros/luatex/generic/luamplib')
-rw-r--r--macros/luatex/generic/luamplib/Makefile96
-rw-r--r--macros/luatex/generic/luamplib/NEWS202
-rw-r--r--macros/luatex/generic/luamplib/README62
-rw-r--r--macros/luatex/generic/luamplib/luamplib.dtx2713
-rw-r--r--macros/luatex/generic/luamplib/luamplib.pdfbin0 -> 148871 bytes
-rw-r--r--macros/luatex/generic/luamplib/test-luamplib-latex.tex164
-rw-r--r--macros/luatex/generic/luamplib/test-luamplib-plain.tex162
7 files changed, 3399 insertions, 0 deletions
diff --git a/macros/luatex/generic/luamplib/Makefile b/macros/luatex/generic/luamplib/Makefile
new file mode 100644
index 0000000000..a842e2c30b
--- /dev/null
+++ b/macros/luatex/generic/luamplib/Makefile
@@ -0,0 +1,96 @@
+NAME = luamplib
+FORMAT = luatex
+
+DTX = $(NAME).dtx
+DOC = $(NAME).pdf
+STY = $(NAME).sty
+LUA = $(NAME).lua
+TEST = test-$(NAME)-plain.tex test-$(NAME)-latex.tex
+
+UNPACKED = $(STY) $(LUA)
+GENERATED = $(UNPACKED) $(DOC)
+SOURCES = $(DTX) README NEWS Makefile $(TEST)
+
+DOCFILES = $(DOC) $(TEST) README NEWS
+SRCFILES = $(DTX) Makefile
+RUNFILES = $(STY) $(LUA)
+
+ALL = $(SRCFILES) $(DOCFILES) $(RUNFILES)
+
+RUNDIR = $(TEXMFDIR)/tex/$(FORMAT)/$(NAME)
+DOCDIR = $(TEXMFDIR)/doc/$(FORMAT)/$(NAME)
+SRCDIR = $(TEXMFDIR)/source/$(FORMAT)/$(NAME)
+TEXMFDIR = $(shell kpsewhich --var-value TEXMFHOME)
+
+CTAN_ZIP = $(NAME).zip
+TDS_ZIP = $(NAME).tds.zip
+ZIPS = $(CTAN_ZIP) $(TDS_ZIP)
+
+all: $(GENERATED)
+doc: $(DOC)
+unpack: $(UNPACKED)
+ctan: check $(CTAN_ZIP)
+tds: $(TDS_ZIP)
+world: all ctan
+
+.PHONY: all doc unpack ctan tds check world
+
+%.pdf: %.dtx
+ latexmk -lualatex -recorder- -silent $< >/dev/null
+
+$(UNPACKED): $(DTX)
+ luatex -interaction=batchmode $< >/dev/null
+
+check: $(UNPACKED)
+ luatex -interaction=batchmode test-$(NAME)-plain.tex >/dev/null
+ lualatex -interaction=batchmode test-$(NAME)-latex.tex >/dev/null
+ ! grep "blank space" test-$(NAME)-plain.log
+ ! grep "blank space" test-$(NAME)-latex.log
+
+$(CTAN_ZIP): $(SOURCES) $(DOC) $(TDS_ZIP)
+ @echo "Making $@ for CTAN upload."
+ @$(RM) -- $@
+ @mkdir -p $(NAME)
+ @cp -f $(SOURCES) $(DOC) $(NAME)
+ @zip -q -9 -r $@ $(TDS_ZIP) $(NAME)
+ @$(RM) -r $(NAME)
+
+define run-install
+@mkdir -p $(RUNDIR) && cp $(RUNFILES) $(RUNDIR)
+@mkdir -p $(DOCDIR) && cp $(DOCFILES) $(DOCDIR)
+@mkdir -p $(SRCDIR) && cp $(SRCFILES) $(SRCDIR)
+endef
+
+$(TDS_ZIP): TEXMFDIR=./tmp-texmf
+$(TDS_ZIP): $(ALL)
+ @echo "Making TDS-ready archive $@."
+ @$(RM) -- $@
+ @if test -e $(TEXMFDIR); then echo 'bad TEXMFDIR'; false; fi
+ $(run-install)
+ @cd $(TEXMFDIR) && zip -q -9 ../$@ -r .
+ @$(RM) -r -- $(TEXMFDIR)
+
+.PHONY: install clean mrproper help
+
+install: check $(ALL)
+ @echo "Installing in '$(TEXMFDIR)'."
+ $(run-install)
+
+clean:
+ @latexmk -silent -c $(DTX) *.tex >/dev/null
+ @rm -f -- *.log test*.pdf
+
+mrproper: clean
+ @rm -f -- $(GENERATED) $(ZIPS)
+
+help:
+ @echo '$(NAME) makefile targets:'
+ @echo ' help - (this message)'
+ @echo ' all - (default target) all generated files'
+ @echo ' world - synonymous for ctan'
+ @echo ' unpack - extract all files'
+ @echo ' doc - compile documentation'
+ @echo ' ctan - run check & generate archive for CTAN'
+ @echo ' tds - generate a TDS compliant archive'
+ @echo ' check - run the test files'
+ @echo ' install TEXMFDIR=<path> - install in <path>'
diff --git a/macros/luatex/generic/luamplib/NEWS b/macros/luatex/generic/luamplib/NEWS
new file mode 100644
index 0000000000..22279f9c35
--- /dev/null
+++ b/macros/luatex/generic/luamplib/NEWS
@@ -0,0 +1,202 @@
+ History of the luamplib package
+
+2019/03/26 2.20.1
+ * '\mpdim' and '\mpcolor' are allowed, even if '\mplibverbatim' is enabled.
+
+2019/03/20 2.20.0
+ * huge changes, but mostly internal, so apparently not much difference
+ from previous version.
+ * '\mplibforcehmode' makes mplibcode typeset in horizontal mode.
+ '\mplibnoforcehmode' reverts the setting. The latter is default.
+ * '\mpliblegacybehavior{disable}' triggers a new mode of processing
+ verbatimtex .. etex: along with btex .. etex, they will be processed
+ sequentially one by one. Old behavior, being default, can be restored
+ by declaring '\mpliblegacybehavior{enable}'.
+ Incidentally, verbatimtex .. etex in MP input files is honored
+ from this version, save those that contain '\documentclass'
+ or '\begin{document}' etc, which is totally ignored.
+
+2018/09/27 2.12.5
+ * change dash.offset pattern from "%i" to "%f" (PR #77)
+ * remove unnecessary variables that go back to context (issue #76)
+
+2018/04/16 2.12.4
+ * workaround issue #74 relating to PATH limitation
+ * substitute InconsolataN font for Liberation Mono in the manual
+
+2018/04/06 2.12.3
+ * step copyright year
+ * remove a line relating graphictext hindrance
+
+2018/01/04 2.12.2
+ * workaround issue #70 "Labels outside beginfig...endfig are not inherited"
+ * address issue #71 "metafun problem: arrow tips are not filled"
+ by importing luatex-mplib.lua from context beta.
+
+2017/06/02 2.12.1
+ * when \mplibglobaltextext{enable} is declared, metapost variables
+ containing btex ... etex labels can be inherited across code chunks.
+ Of course, \mplibcodeinherit should also be switched on.
+
+2016/03/31 2.11.3
+ * fix a bug regarding nested mplibcode environments (issue #63)
+
+2016/01/02 2.11.2
+ * updates for luatex 0.87
+
+2015/10/02 2.11.1
+ * adapts to latex 2015/10/01 and luatexbase v1.0
+ * allows `btex ... etex' and `verbatimtex ... etex' even when
+ `\mplibverbatim{enable}' is declared.
+
+2015/08/01 2.11.0
+ * after `\mplibverbatim{enable}', contents of mplibcode environment
+ will be read verbatim. So `btex ... etex', `verbatimtex ... etex',
+ `\mpdim', `\mpcolor' are not allowed and all TeX commands will be
+ fed literally into mplib library.
+ * allow access to type1 fonts, which means we can use glyph
+ operator now (luatex rev 5266)
+ * color transparency is now compatible with pgf package and
+ beamer class as well. (luatex 0.80+ is recommended)
+
+2015/03/26 2.10.1
+ * fix bug #55 regarding hash token
+
+2015/03/20 2.10.0
+ * TeX code in `VerbatimTeX()' between `beginfig();' and `endfig;'
+ will be inserted after flushing out the mplib figure.
+ * `\mpcolor' command accepts optional argument: for instance,
+ `\mpcolor[HTML]{FF0000}'.
+
+2015/01/26 2.9.1
+ * fix a bug reported by Herbert Schulz via luatex mailing list
+ (http://tug.org/pipermail/luatex/2015-January/005054.html)
+
+2015/01/05 2.9.0
+ * after declaring `\mplibcodeinherit{enable}', each mplib code chunks
+ will inherit variables/constants/macros defined by previous chunks.
+ On the contrary, the default value `\mplibcodeinherit{disable}' will
+ treat each code chunks as an independent instance, never being affected
+ by other code chunks.
+
+2014/07/04 2.8.1
+ * support color package on plain tex.
+ * fix a failure at `btex \% etex'.
+
+2014/06/17 2.8.0
+ * support color/xcolor/spotcolor packages.
+ On LaTeX, color names or expressions of color/xcolor packages
+ can be used inside mplibcode environment with the command
+ \mpcolor{<color expression>}.
+
+2014/04/25 2.7.0
+ * support DVIPDFMx
+ * default directory for cache is now '$TEXMFVAR/luamplib_cache'
+ * internal changes following LuaTeX engine v0.79 and luatexbase
+ package v0.7
+ * [fix] avoid luatex crash under math_mode 'decimal'
+
+2014/03/26 2.6.1
+ * now luamplib does not disregard 'show' command, even if
+ 'luamplib.showlog' is false. Incidentally, it does not raise
+ error, but just prints a warning, even if output contains
+ no figure.
+ * fix a bug wrt color, which might come to the fore under
+ math mode 'double' or 'decimal'.
+
+2014/03/08 2.6.0
+ * new macro \mplibtextextlabel{enable} enables string labels typeset
+ with textext() instead of infont operator. Every string label
+ thereafter will be typeset with current TeX font.
+ * fixed a bug wrt btex ... etex parsing (issue #39)
+ * [doc] added a mention about \MPllx, \MPlly, \MPurx, and \MPury.
+
+2014/03/01 2.5.3
+ * using \mplibcachedir{<directory path>}, users can change the
+ directory for storing cache files. By default, it is the directory
+ where pdf output file is saved.
+ * at the end of package loading, luamplib searches 'luamplib.cfg',
+ and, when found, reads the file in automatically.
+
+2014/02/24 2.5.2
+ * new macros \mplibmakenocache{...} and \mplibcancelnocache{...} to
+ register/unregister those .mp files that do not need caches.
+ These macros affect the compilation speed only.
+ * added a hack to support graph.mp (in fact, format.mp)
+ * [fix] luamplib now respects percent sign if it is enclosed by quotes.
+
+2014/02/19 2.5
+ * btex ... etex input from external *.mp files will also be processed
+ by luamplib. However, verbatimtex ... etex will be entirely ignored
+ in this case.
+
+2014/02/02 2.4
+ * implemented "numbersystem" option. Default value "scaled" can be
+ changed by declaring \mplibnumbersystem{double}. For details, see
+ http://github.com/lualatex/luamplib/issues/21
+
+2014/01/20 2.3
+ * \everymplib, \everyendmplib: macros that redefine token lists
+ \everymplibtoks and \everyendmplibtoks. These will be
+ automatically inserted at the beginning and ending (respectively)
+ of each and every mplib code.
+ * naked TeX codes, includig \mpdim{...}, are allowed inside
+ mplibcode environment. Refer the manual of gmp package for
+ details.
+
+2013/12/30 2.2
+ * start to support transparency/shading under metafun format.
+ * verbatimtex ... etex just before beginfig() is not ignored.
+ Using this macro, each mplib box can be moved horizontally and/or
+ vertically.
+
+2013/12/23 2.1.1
+ * fix a bug wrt "withoutcolor" option
+ * fix a bug wrt "char <number> infont <font>" picture
+ * bypass some ConTeXt commands which raise errors under metafun format
+ * ignore "fontmapfile <filename>" which isn't needed in mplib
+
+2013/12/19 2.1
+ * Do not ignore "withcolor" option for textext and normal text object
+ * verbatimtex ... etex is now just ignored, not raising error
+
+2013/12/11 2.03
+ * implemented textext() macro which is identical to TEX() from TEX.mp.
+ TEX() is a synonym of textext().
+ * fix a bug regarding tex-text box inside for...endfor loop,
+ reported at http://www.ktug.org/xe/index.php?document_srl=178050
+
+2013/09/24 2.01
+ * fix bug reported by Stephan Hennig: wrong baseline of tex-text box
+
+2013/05/07 2.0
+ * Update with current ConTeXt code
+ * Adding the possibility of btex...etex commands (Kim)
+
+2011/12/09 1.09
+ * Fix bug reported by Paul Vojta: spurious spaces.
+
+2011/06/23 1.08
+ * Fix bug reported by Rolf Dieterich: <, >, TAB anywhere in a luacode
+ environment caused errors. The character ` was affected too.
+
+2010/12/28 1.07
+ * fix two bugs reported by Arno Trautmann that made the package crash with
+ luatex 0.65 (mp 1.5+).
+ * remove support for using .mem files (to fix the second bug)
+
+2010/10/17 v1.06
+ * bugfix from Hans (bad function name)
+
+2010/10/10 v1.05
+ * adapt to luatexbase v0.3
+
+2010/08/02 v1.04
+ * fixing a bug in LaTeX's detection (made Tikz fail)
+ * setting luamplib-luatex as the default name for the format, it's the case
+ in TeXLive 2010
+ * adding two test files in the git repository
+
+2010/05/10 v1.03
+ * adaptation to the new luatexbase package
+
diff --git a/macros/luatex/generic/luamplib/README b/macros/luatex/generic/luamplib/README
new file mode 100644
index 0000000000..9518912982
--- /dev/null
+++ b/macros/luatex/generic/luamplib/README
@@ -0,0 +1,62 @@
+ The luamplib generic package.
+
+
+This package allows typesetting of metapost natively in the TeX documents
+thanks to the LuaTeX mplib library. It works in PDF or DVI mode, but
+DVIPDFMx is the only DVI tool currently supported.
+
+This package is developed on <http://github.com/lualatex/luamplib>.
+
+
+Installation
+------------
+
+Here are the recommended installation methods (preferred first).
+
+1. If you are using TeX Live 2008 or later, use 'tlmgr install luamplib'.
+Alternatively, try your (TeX or Linux) distribution's package management system.
+
+2. a. Grab the sources from CTAN or github.
+ b. Run 'make install TEXMFDIR=/path/to/texmf'.
+ c. You may need to update some filename database after, see your TeX
+distribution's manual for details.
+
+3. Try to figure it out by looking at the Makefile and comments in the sources.
+
+
+Manifest
+--------
+
+Source files:
+ luamplib.dtx single file source & doc
+
+Derived files:
+ luamplib.pdf documentation
+ luamplib.sty package
+ luamplib.lua lua code used by the package
+
+
+License
+-------
+
+The luamplib bundle, as a derived work of ConTeXt, is distributed under the
+GNU GPLv2 license:
+
+ <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>
+
+This license requires the license itself to be distributed with the work. For
+its full text see the documentation in luamplib.pdf.
+
+
+ DISCLAIMER
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; version 2.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ See headers of each source file for copyright details.
diff --git a/macros/luatex/generic/luamplib/luamplib.dtx b/macros/luatex/generic/luamplib/luamplib.dtx
new file mode 100644
index 0000000000..8524830d78
--- /dev/null
+++ b/macros/luatex/generic/luamplib/luamplib.dtx
@@ -0,0 +1,2713 @@
+% \iffalse meta-comment -- by the way, this file contains UTF-8
+%
+% Copyright (C) 2008-2019 by Hans Hagen, Taco Hoekwater, Elie Roux,
+% Manuel Pégourié-Gonnard, Philipp Gesang and Kim Dohyun.
+% Currently maintained by the LuaLaTeX development team.
+% Support: <lualatex-dev@tug.org>
+%
+% This work is under the GPL v2.0 license.
+%
+% This work consists of the main source file luamplib.dtx
+% and the derived files
+% luamplib.sty, luamplib.lua and luamplib.pdf.
+%
+% Unpacking:
+% tex luamplib.dtx
+%
+% Documentation:
+% lualatex luamplib.dtx
+%
+%<*ignore>
+\begingroup
+ \def\x{LaTeX2e}%
+\expandafter\endgroup
+\ifcase 0\ifx\install y1\fi\expandafter
+ \ifx\csname processbatchFile\endcsname\relax\else1\fi
+ \ifx\fmtname\x\else 1\fi\relax
+\else\csname fi\endcsname
+%</ignore>
+%<*install>
+\input docstrip.tex
+\Msg{************************************************************************}
+\Msg{* Installation}
+\Msg{* Package: luamplib - metapost package for LuaTeX.}
+\Msg{************************************************************************}
+
+\keepsilent
+\askforoverwritefalse
+
+\let\MetaPrefix\relax
+
+\preamble
+
+See source file '\inFileName' for licencing and contact information.
+
+\endpreamble
+
+\let\MetaPrefix\DoubleperCent
+
+\generate{%
+ \usedir{tex/luatex/luamplib}%
+ \file{luamplib.sty}{\from{luamplib.dtx}{package}}%
+}
+
+\def\MetaPrefix{-- }
+
+\def\luapostamble{%
+ \MetaPrefix^^J%
+ \MetaPrefix\space End of File `\outFileName'.%
+}
+
+\def\currentpostamble{\luapostamble}%
+
+\generate{%
+ \usedir{tex/luatex/luamplib}%
+ \file{luamplib.lua}{\from{luamplib.dtx}{lua}}%
+}
+
+\obeyspaces
+\Msg{************************************************************************}
+\Msg{*}
+\Msg{* To finish the installation you have to move the following}
+\Msg{* files into a directory searched by TeX:}
+\Msg{*}
+\Msg{* luamplib.sty luamplib.lua}
+\Msg{*}
+\Msg{* Happy TeXing!}
+\Msg{*}
+\Msg{************************************************************************}
+
+\endbatchfile
+%</install>
+%<*ignore>
+\fi
+%</ignore>
+%<*driver>
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesFile{luamplib.drv}%
+ [2019/03/26 v2.20.1 Interface for using the mplib library]%
+\documentclass{ltxdoc}
+\usepackage{metalogo,multicol,mdwlist,fancyvrb,xspace}
+\usepackage[x11names]{xcolor}
+%
+\def\primarycolor{DodgerBlue4} %%-> rgb 16 78 139 | #104e8b
+\def\secondarycolor{Goldenrod4} %%-> rgb 139 105 200 | #8b6914
+%
+\usepackage[
+ bookmarks=true,
+ colorlinks=true,
+ linkcolor=\primarycolor,
+ urlcolor=\secondarycolor,
+ citecolor=\primarycolor,
+ pdftitle={The luamplib package},
+ pdfsubject={Interface for using the mplib library},
+ pdfauthor={Hans Hagen, Taco Hoekwater, Elie Roux, Philipp Gesang & Kim Dohyun},
+ pdfkeywords={luatex, lualatex, mplib, metapost}
+]{hyperref}
+\usepackage{fontspec}
+\setmainfont[
+ Numbers = OldStyle,
+ Ligatures = TeX,
+ BoldFont = {Linux Libertine O Bold},
+ ItalicFont = {Linux Libertine O Italic},
+ SlantedFont = {Linux Libertine O Italic},
+]{Linux Libertine O}
+\setmonofont[Ligatures=TeX,Scale=MatchLowercase]{InconsolataN}
+%setsansfont[Ligatures=TeX]{Linux Biolinum O}
+\setsansfont[Ligatures=TeX,Scale=MatchLowercase]{Iwona Medium}
+%setmathfont{XITS Math}
+
+\usepackage{hologo}
+
+\newcommand\ConTeXt {Con\TeX t\xspace}
+
+\newcommand*\email [1] {<\href{mailto:#1}{#1}>}
+\newcommand \file {\nolinkurl}
+\newcommand \pk {\textsf}
+
+\begin{document}
+ \DocInput{luamplib.dtx}%
+\end{document}
+%</driver>
+% \fi
+%
+% \CheckSum{0}
+%
+% \CharacterTable
+% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+% Digits \0\1\2\3\4\5\6\7\8\9
+% Exclamation \! Double quote \" Hash (number) \#
+% Dollar \$ Percent \% Ampersand \&
+% Acute accent \' Left paren \( Right paren \)
+% Asterisk \* Plus \+ Comma \,
+% Minus \- Point \. Solidus \/
+% Colon \: Semicolon \; Less than \<
+% Equals \= Greater than \> Question mark \?
+% Commercial at \@ Left bracket \[ Backslash \\
+% Right bracket \] Circumflex \^ Underscore \_
+% Grave accent \` Left brace \{ Vertical bar \|
+% Right brace \} Tilde \~}
+%
+% \title{The \textsf{luamplib} package}
+% \author{Hans Hagen, Taco Hoekwater, Elie Roux, Philipp Gesang and Kim Dohyun\\
+% Maintainer: LuaLaTeX Maintainers ---
+% Support: \email{lualatex-dev@tug.org}}
+% \date{2019/03/26 v2.20.1}
+%
+% \maketitle
+%
+% \begin{abstract}
+% Package to have metapost code typeset directly in a document with \LuaTeX.
+% \end{abstract}
+%
+% \section{Documentation}
+%
+% This packages aims at providing a simple way to typeset directly metapost
+% code in a document with \LuaTeX. \LuaTeX\ is built with the lua
+% \texttt{mplib} library, that runs metapost code. This package is basically a
+% wrapper (in Lua) for the Lua \texttt{mplib} functions and some \TeX\
+% functions to have the output of the \texttt{mplib} functions in the pdf.
+%
+% In the past,
+% the package required PDF mode in order to output something.
+% Starting with version 2.7 it works in DVI mode as well, though
+% DVIPDFMx is the only DVI tool currently supported.
+%
+% The metapost figures are put in a \TeX\ \texttt{hbox} with dimensions
+% adjusted to the metapost code.
+%
+% Using this package is easy: in Plain, type your metapost code between the
+% macros \cs{mplibcode} and \cs{endmplibcode}, and in \LaTeX\ in the
+% \texttt{mplibcode} environment.
+%
+% The code is from the \texttt{luatex-mplib.lua} and \texttt{luatex-mplib.tex} files
+% from \ConTeXt, they have been adapted to \LaTeX\ and Plain by Elie Roux and
+% Philipp Gesang, new functionalities have been added by Kim Dohyun.
+% The changes are:
+%
+% \begin{itemize}
+% \item a \LaTeX\ environment
+% \item all \TeX\ macros start by |mplib|
+% \item use of luatexbase for errors, warnings and declaration
+% \item possibility to use |btex ... etex| to typeset \TeX\ code.
+% |textext()| is a more versatile macro equivalent to |TEX()| from TEX.mp.
+% |TEX()| is also allowed and is a synomym of |textext()|.\par\smallskip
+% \textsc{n.b.} Since v2.5, |btex ... etex| input from external |mp| files
+% will also be processed by \textsf{luamplib}.\par\smallskip
+% \textsc{n.b.} Since v2.20, |verbatimtex ... etex| from external |mp| files
+% will be also processed by \textsf{luamplib}. Warning: This is a change
+% from previous version.
+% \end{itemize}
+%
+% Some more changes and cautions are:
+%
+% \paragraph{\cs{mplibforcehmode}}
+% When this macro is declared, every mplibcode figure box will be
+% typeset in horizontal mode, so \cs{centering}, \cs{raggedleft} etc
+% will have effects. |\mplibnoforcehmode|, being default, reverts this
+% setting.
+%
+% \paragraph{\cs{mpliblegacybehavior\{enable\}}}
+% By default, |\mpliblegacybehavior{enable}| is already declared,
+% in which case
+% a |verbatimtex ... etex| that comes just before |beginfig()|
+% is not ignored, but the \TeX\ code will be inserted before the
+% following mplib hbox. Using this command,
+% each mplib box can be freely moved horizontally and/or vertically.
+% Also, a box number might be assigned to mplib box, allowing it to be
+% reused later (see test files).
+% \begin{verbatim}
+% \mplibcode
+% verbatimtex \moveright 3cm etex; beginfig(0); ... endfig;
+% verbatimtex \leavevmode etex; beginfig(1); ... endfig;
+% verbatimtex \leavevmode\lower 1ex etex; beginfig(2); ... endfig;
+% verbatimtex \endgraf\moveright 1cm etex; beginfig(3); ... endfig;
+% \endmplibcode
+% \end{verbatim}
+% \textsc{n.b.} \cs{endgraf} should be used instead of \cs{par} inside
+% |verbatimtex ... etex|.
+%
+% By contrast, \TeX\ code in |VerbatimTeX(...)| or |verbatimtex ... etex|
+% between |beginfig()| and |endfig| will be inserted
+% after flushing out the mplib figure.
+% \begin{verbatim}
+% \mplibcode
+% D := sqrt(2)**7;
+% beginfig(0);
+% draw fullcircle scaled D;
+% VerbatimTeX("\gdef\Dia{" & decimal D & "}");
+% endfig;
+% \endmplibcode
+% diameter: \Dia bp.
+% \end{verbatim}
+%
+% \paragraph{\cs{mpliblegacybehavior\{disable\}}}
+% If |\mpliblegacybehavior{disabled}| is declared by user, any
+% |verbatimtex ... etex| will be executed, along with |btex ... etex|,
+% sequentially one by one.
+% So, some \TeX\ code in |verbatimtex ... etex| will have effects on
+% |btex ... etex| codes that follows.
+% \begin{verbatim}
+% \begin{mplibcode}
+% beginfig(0);
+% draw btex ABC etex;
+% verbatimtex \bfseries etex;
+% draw btex DEF etex shifted (1cm,0); % bold face
+% draw btex GHI etex shifted (2cm,0); % bold face
+% endfig;
+% \end{mplibcode}
+% \end{verbatim}
+%
+% \paragraph{About figure box metrics}
+% Notice that, after each figure is processed, macro \cs{MPwidth} stores
+% the width value of latest figure; \cs{MPheight}, the height value.
+% Incidentally, also note that \cs{MPllx}, \cs{MPlly}, \cs{MPurx}, and
+% \cs{MPury} store the bounding box information of latest figure
+% without the unit |bp|.
+%
+% \paragraph{\cs{everymplib}, \cs{everyendmplib}}
+% Since v2.3, new macros \cs{everymplib} and \cs{everyendmplib} redefine
+% token lists \cs{everymplibtoks} and \cs{everyendmplibtoks} respectively,
+% which will
+% be automatically inserted at the beginning and ending of each mplib code.
+% \begin{verbatim}
+% \everymplib{ beginfig(0); }
+% \everyendmplib{ endfig; }
+% \mplibcode % beginfig/endfig not needed
+% draw fullcircle scaled 1cm;
+% \endmplibcode
+% \end{verbatim}
+%
+% \paragraph{\cs{mpdim}}
+% Since v2.3, \cs{mpdim} and other raw \TeX\ commands are allowed
+% inside mplib code. This feature is inpired by gmp.sty authored by
+% Enrico Gregorio. Please refer the manual of gmp package for details.
+% \begin{verbatim}
+% \begin{mplibcode}
+% draw origin--(\mpdim{\linewidth},0) withpen pencircle scaled 4
+% dashed evenly scaled 4 withcolor \mpcolor{orange};
+% \end{mplibcode}
+% \end{verbatim}
+% \textsc{n.b.} Users should not use the protected variant of
+% |btex ... etex| as provided by gmp package. As \textsf{luamplib}
+% automatically protects \TeX\ code inbetween, \cs{btex} is not supported
+% here.
+%
+% \paragraph{\cs{mpcolor}}
+% With \cs{mpcolor} command, color names or expressions of
+% \textsf{color}/\textsf{xcolor} packages can be used inside mplibcode
+% enviroment, though \textsf{luamplib} does not automatically load these
+% packages. See the example code above. For spot colors, \textsf{(x)spotcolor}
+% (in PDF mode) and \textsf{xespotcolor} (in DVI mode) packages are supported
+% as well.
+%
+% \paragraph{\cs{mplibnumbersystem}}
+% Users can choose |numbersystem| option since v2.4.
+% The default value |scaled| can be changed to |double| or |decimal|
+% by declaring |\mplibnumbersystem{double}| or |\mplibnumbersystem{decimal}|.
+% For details see
+% \url{http://github.com/lualatex/luamplib/issues/21}.
+%
+% \paragraph{Settings regarding cache files}
+% To support |btex ... etex| in external |.mp| files, \textsf{luamplib}
+% inspects the content of each and every |.mp| input files and makes caches
+% if nececcsary, before returning their paths to \LuaTeX's mplib library.
+% This would make the compilation time longer wastefully, as most |.mp| files
+% do not contain |btex ... etex| command. So \textsf{luamplib} provides
+% macros as follows, so that users can give instruction about files
+% that do not require this functionality.
+% \begin{itemize}
+% \item |\mplibmakenocache{<filename>[,<filename>,...]}|
+% \item |\mplibcancelnocache{<filename>[,<filename>,...]}|
+% \end{itemize}
+% where |<filename>| is a file name excluding |.mp| extension.
+% Note that |.mp| files under |$TEXMFMAIN/metapost/base| and
+% |$TEXMFMAIN/metapost/context/base| are already registered by default.
+%
+% By default, cache files will be stored in |$TEXMFVAR/luamplib_cache| or,
+% if it's not available, in the same directory as where pdf/dvi output file
+% is saved. This however can be changed by the command
+% |\mplibcachedir{<directory path>}|, where tilde (|~|) is interpreted
+% as the user's home directory (on a windows machine as well).
+% As backslashes (|\|) should be escaped by users, it would be easier to use
+% slashes (|/|) instead.
+%
+% \paragraph{\cs{mplibtextextlabel}}
+% Starting with v2.6, |\mplibtextextlabel{enable}| enables
+% string labels typeset via |textext()| instead of |infont| operator.
+% So, |label("my text",origin)| thereafter is exactly the same as
+% |label(textext("my text"),origin)|. \textsc{n.b.} In the background,
+% \textsf{luamplib} redefines |infont| operator so that the right side
+% argument (the font part) is totally ignored. Every string label
+% therefore will be typeset with current \TeX\ font.
+% Also take care of |char| operator in the left side argument,
+% as this might bring unpermitted characters into \TeX.
+%
+% \paragraph{\cs{mplibcodeinherit}}
+% Starting with v2.9, |\mplibcodeinherit{enable}| enables the inheritance
+% of variables, constants, and macros defined by previous |mplibcode| chunks.
+% On the contrary, the default value |\mplibcodeinherit{disable}| will make
+% each code chunks being treated as an independent instance, and never
+% affected by previous code chunks.
+%
+% \paragraph{\cs{mplibglobaltextext}}
+% To inherit |btex ... etex| labels as well as metapost variables,
+% it is necessary to declare \cs{mplibglobaltextext\{enable\}} in advance.
+% On this case, be careful that normal \TeX\ boxes can conflict with
+% |btex ... etex| boxes, though this would occur very rarely.
+% Notwithstanding the danger, it is a `must' option to activate
+% \cs{mplibglobaltextext} if you want to use |graph.mp|
+% with \cs{mplibcodeinherit} functionality.
+% \begin{verbatim}
+% \mplibcodeinherit{enable}
+% \mplibglobaltextext{enable}
+% \everymplib{ beginfig(0);} \everyendmplib{ endfig;}
+% \mplibcode
+% label(btex $\sqrt{2}$ etex, origin);
+% draw fullcircle scaled 20;
+% picture pic; pic := currentpicture;
+% \endmplibcode
+% \mplibcode
+% currentpicture := pic scaled 2;
+% \endmplibcode
+% \end{verbatim}
+%
+% \paragraph{\cs{mplibverbatim}}
+% Starting with v2.11, users can issue |\mplibverbatim{enable}|, after which
+% the contents of mplibcode environment will be read verbatim. As a result,
+% except for |\mpdim| and |\mpcolor|, all other \TeX\ commands outside
+% |btex ... etex| or |verbatimtex ... etex| are not expanded and will be fed
+% literally into the mplib process.
+%
+% \paragraph{luamplib.cfg}
+% At the end of package loading, \textsf{luamplib} searches
+% |luamplib.cfg| and, if found, reads the file in automatically.
+% Frequently used settings such as \cs{everymplib} or \cs{mplibforcehmode}
+% are suitable for going into this file.
+%
+% \bigskip
+%
+% There are (basically) two formats for metapost: \emph{plain} and
+% \emph{metafun}. By default, the \emph{plain} format is used, but you can set
+% the format to be used by future figures at any time using
+% \cs{mplibsetformat}\marg{format name}.
+%
+% \section{Implementation}
+%
+% \subsection{Lua module}
+%
+% \iffalse
+%<*lua>
+% \fi
+%
+% \begin{macrocode}
+
+luatexbase.provides_module {
+ name = "luamplib",
+ version = "2.20.1",
+ date = "2019/03/26",
+ description = "Lua package to typeset Metapost with LuaTeX's MPLib.",
+}
+
+local format, abs = string.format, math.abs
+
+local err = function(...) return luatexbase.module_error ("luamplib", format(...)) end
+local warn = function(...) return luatexbase.module_warning("luamplib", format(...)) end
+local info = function(...) return luatexbase.module_info ("luamplib", format(...)) end
+
+% \end{macrocode}
+%
+% Use the |luamplib| namespace, since |mplib| is for the metapost library
+% itself. \ConTeXt{} uses |metapost|.
+% \begin{macrocode}
+luamplib = luamplib or { }
+local luamplib = luamplib
+
+luamplib.showlog = luamplib.showlog or false
+luamplib.lastlog = ""
+
+% \end{macrocode}
+%
+% This module is a stripped down version of libraries that are used by
+% \ConTeXt. Provide a few ``shortcuts'' expected by the imported code.
+% \begin{macrocode}
+local tableconcat = table.concat
+local texsprint = tex.sprint
+local textprint = tex.tprint
+
+local texget = tex.get
+local texgettoks = tex.gettoks
+local texgetbox = tex.getbox
+local texruntoks = tex.runtoks
+% \end{macrocode}
+%
+% We don't use |tex.scantoks| anymore. See below reagrding |tex.runtoks|.
+% \begin{verbatim}
+% local texscantoks = tex.scantoks
+% \end{verbatim}
+% \begin{macrocode}
+
+if not texruntoks then
+ err("Your LuaTeX version is too old. Please upgrade it to the latest")
+end
+
+local mplib = require ('mplib')
+local kpse = require ('kpse')
+local lfs = require ('lfs')
+
+local lfsattributes = lfs.attributes
+local lfsisdir = lfs.isdir
+local lfsmkdir = lfs.mkdir
+local lfstouch = lfs.touch
+local ioopen = io.open
+
+% \end{macrocode}
+%
+% Some helper functions, prepared for the case when |l-file| etc
+% is not loaded.
+% \begin{macrocode}
+local file = file or { }
+local replacesuffix = file.replacesuffix or function(filename, suffix)
+ return (filename:gsub("%.[%a%d]+$","")) .. "." .. suffix
+end
+local stripsuffix = file.stripsuffix or function(filename)
+ return (filename:gsub("%.[%a%d]+$",""))
+end
+
+local is_writable = file.is_writable or function(name)
+ if lfsisdir(name) then
+ name = name .. "/_luam_plib_temp_file_"
+ local fh = ioopen(name,"w")
+ if fh then
+ fh:close(); os.remove(name)
+ return true
+ end
+ end
+end
+local mk_full_path = lfs.mkdirs or function(path)
+ local full = ""
+ for sub in path:gmatch("(/*[^\\/]+)") do
+ full = full .. sub
+ lfsmkdir(full)
+ end
+end
+
+% \end{macrocode}
+%
+% |btex ... etex| in input |.mp| files will be replaced in finder.
+% Because of the limitation of MPLib regarding |make_text|,
+% we might have to make cache files modified from input files.
+% \begin{macrocode}
+local luamplibtime = kpse.find_file("luamplib.lua")
+luamplibtime = luamplibtime and lfsattributes(luamplibtime,"modification")
+
+local currenttime = os.time()
+
+local outputdir
+if lfstouch then
+ local texmfvar = kpse.expand_var('$TEXMFVAR')
+ if texmfvar and texmfvar ~= "" and texmfvar ~= '$TEXMFVAR' then
+ for _,dir in next, texmfvar:explode(os.type == "windows" and ";" or ":") do
+ if not lfsisdir(dir) then
+ mk_full_path(dir)
+ end
+ if is_writable(dir) then
+ local cached = format("%s/luamplib_cache",dir)
+ lfsmkdir(cached)
+ outputdir = cached
+ break
+ end
+ end
+ end
+end
+if not outputdir then
+ outputdir = "."
+ for _,v in ipairs(arg) do
+ local t = v:match("%-output%-directory=(.+)")
+ if t then
+ outputdir = t
+ break
+ end
+ end
+end
+
+function luamplib.getcachedir(dir)
+ dir = dir:gsub("##","#")
+ dir = dir:gsub("^~",
+ os.type == "windows" and os.getenv("UserProfile") or os.getenv("HOME"))
+ if lfstouch and dir then
+ if lfsisdir(dir) then
+ if is_writable(dir) then
+ luamplib.cachedir = dir
+ else
+ warn("Directory '"..dir.."' is not writable!")
+ end
+ else
+ warn("Directory '"..dir.."' does not exist!")
+ end
+ end
+end
+
+% \end{macrocode}
+%
+% Some basic MetaPost files not necessary to make cache files.
+% \begin{macrocode}
+local noneedtoreplace = {
+ ["boxes.mp"] = true, -- ["format.mp"] = true,
+ ["graph.mp"] = true, ["marith.mp"] = true, ["mfplain.mp"] = true,
+ ["mpost.mp"] = true, ["plain.mp"] = true, ["rboxes.mp"] = true,
+ ["sarith.mp"] = true, ["string.mp"] = true, -- ["TEX.mp"] = true,
+ ["metafun.mp"] = true, ["metafun.mpiv"] = true, ["mp-abck.mpiv"] = true,
+ ["mp-apos.mpiv"] = true, ["mp-asnc.mpiv"] = true, ["mp-bare.mpiv"] = true,
+ ["mp-base.mpiv"] = true, ["mp-blob.mpiv"] = true, ["mp-butt.mpiv"] = true,
+ ["mp-char.mpiv"] = true, ["mp-chem.mpiv"] = true, ["mp-core.mpiv"] = true,
+ ["mp-crop.mpiv"] = true, ["mp-figs.mpiv"] = true, ["mp-form.mpiv"] = true,
+ ["mp-func.mpiv"] = true, ["mp-grap.mpiv"] = true, ["mp-grid.mpiv"] = true,
+ ["mp-grph.mpiv"] = true, ["mp-idea.mpiv"] = true, ["mp-luas.mpiv"] = true,
+ ["mp-mlib.mpiv"] = true, ["mp-node.mpiv"] = true, ["mp-page.mpiv"] = true,
+ ["mp-shap.mpiv"] = true, ["mp-step.mpiv"] = true, ["mp-text.mpiv"] = true,
+ ["mp-tool.mpiv"] = true,
+}
+luamplib.noneedtoreplace = noneedtoreplace
+
+% \end{macrocode}
+%
+% |format.mp| is much complicated, so specially treated.
+% \begin{macrocode}
+local function replaceformatmp(file,newfile,ofmodify)
+ local fh = ioopen(file,"r")
+ if not fh then return file end
+ local data = fh:read("*all"); fh:close()
+ fh = ioopen(newfile,"w")
+ if not fh then return file end
+ fh:write(
+ "let normalinfont = infont;\n",
+ "primarydef str infont name = rawtextext(str) enddef;\n",
+ data,
+ "vardef Fmant_(expr x) = rawtextext(decimal abs x) enddef;\n",
+ "vardef Fexp_(expr x) = rawtextext(\"$^{\"&decimal x&\"}$\") enddef;\n",
+ "let infont = normalinfont;\n"
+ ); fh:close()
+ lfstouch(newfile,currenttime,ofmodify)
+ return newfile
+end
+
+% \end{macrocode}
+%
+% Replace |btex ... etex| and |verbatimtex ... etex| in input files,
+% if needed.
+% \begin{macrocode}
+local name_b = "%f[%a_]"
+local name_e = "%f[^%a_]"
+local btex_etex = name_b.."btex"..name_e.."%s*(.-)%s*"..name_b.."etex"..name_e
+local verbatimtex_etex = name_b.."verbatimtex"..name_e.."%s*(.-)%s*"..name_b.."etex"..name_e
+
+local function replaceinputmpfile (name,file)
+ local ofmodify = lfsattributes(file,"modification")
+ if not ofmodify then return file end
+ local cachedir = luamplib.cachedir or outputdir
+ local newfile = name:gsub("%W","_")
+ newfile = cachedir .."/luamplib_input_"..newfile
+ if newfile and luamplibtime then
+ local nf = lfsattributes(newfile)
+ if nf and nf.mode == "file" and
+ ofmodify == nf.modification and luamplibtime < nf.access then
+ return nf.size == 0 and file or newfile
+ end
+ end
+
+ if name == "format.mp" then return replaceformatmp(file,newfile,ofmodify) end
+
+ local fh = ioopen(file,"r")
+ if not fh then return file end
+ local data = fh:read("*all"); fh:close()
+
+% \end{macrocode}
+%
+% ``|etex|'' must be followed by a space or semicolon as specified in
+% \LuaTeX\ manual, which is not the case of standalone MetaPost though.
+% \begin{macrocode}
+ local count,cnt = 0,0
+ data, cnt = data:gsub(btex_etex, "btex %1 etex ") -- space
+ count = count + cnt
+ data, cnt = data:gsub(verbatimtex_etex, "verbatimtex %1 etex;") -- semicolon
+ count = count + cnt
+
+ if count == 0 then
+ noneedtoreplace[name] = true
+ fh = ioopen(newfile,"w");
+ if fh then
+ fh:close()
+ lfstouch(newfile,currenttime,ofmodify)
+ end
+ return file
+ end
+
+ fh = ioopen(newfile,"w")
+ if not fh then return file end
+ fh:write(data); fh:close()
+ lfstouch(newfile,currenttime,ofmodify)
+ return newfile
+end
+
+% \end{macrocode}
+%
+% As the finder function for MPLib, use the |kpse| library and
+% make it behave like as if MetaPost was used. And replace it with
+% cache files if needed.
+% \begin{macrocode}
+local mpkpse = kpse.new(arg[0], "mpost")
+
+local special_ftype = {
+ pfb = "type1 fonts",
+ enc = "enc files",
+}
+
+local function finder(name, mode, ftype)
+ if mode == "w" then
+ return name
+ else
+ ftype = special_ftype[ftype] or ftype
+ local file = mpkpse:find_file(name,ftype)
+ if file then
+ if not lfstouch or ftype ~= "mp" or noneedtoreplace[name] then
+ return file
+ end
+ return replaceinputmpfile(name,file)
+ end
+ return mpkpse:find_file(name, name:match("%a+$"))
+ end
+end
+luamplib.finder = finder
+
+% \end{macrocode}
+%
+% Create and load MPLib instances.
+% We do not support ancient version of MPLib any more.
+% (Don't know which version of MPLib started to support
+% |make_text| and |run_script|; let the users find it.)
+% \begin{macrocode}
+if tonumber(mplib.version()) <= 1.50 then
+ err("luamplib no longer supports mplib v1.50 or lower. "..
+ "Please upgrade to the latest version of LuaTeX")
+end
+
+local preamble = [[
+ boolean mplib ; mplib := true ;
+ let dump = endinput ;
+ let normalfontsize = fontsize;
+ input %s ;
+]]
+
+local function luamplibresetlastlog()
+ luamplib.lastlog = ""
+end
+
+local function reporterror (result)
+ if not result then
+ err("no result object returned")
+ else
+ local t, e, l = result.term, result.error, result.log
+ local log = t or l or "no-term"
+ log = log:gsub("^%s+","\n")
+ luamplib.lastlog = luamplib.lastlog .. "\n" .. (l or t or "no-log")
+ if result.status > 0 then
+ warn("%s",log)
+ if result.status > 1 then
+ err("%s",e or "see above messages")
+ end
+ end
+ return log
+ end
+end
+
+local function luamplibload (name)
+ local mpx = mplib.new {
+ ini_version = true,
+ find_file = luamplib.finder,
+% \end{macrocode}
+%
+% Make use of |make_text| and |run_script|, which will co-operate
+% with \LuaTeX's |tex.runtoks|. And we
+% provide |numbersystem| option since v2.4. Default value ``|scaled|''
+% can be changed by declaring |\mplibnumbersystem{double}|
+% or |\mplibnumbersystem{decimal}|.
+% See \url{https://github.com/lualatex/luamplib/issues/21}.
+% \begin{macrocode}
+ make_text = luamplib.maketext,
+ run_script = luamplib.runscript,
+ math_mode = luamplib.numbersystem,
+ extensions = 1,
+ }
+% \end{macrocode}
+%
+% Append our own MetaPost preamble to the preamble above.
+% \begin{macrocode}
+ local preamble = preamble .. luamplib.mplibcodepreamble
+ if luamplib.legacy_verbatimtex then
+ preamble = preamble .. luamplib.legacyverbatimtexpreamble
+ end
+ if luamplib.textextlabel then
+ preamble = preamble .. luamplib.textextlabelpreamble
+ end
+ local result
+ if not mpx then
+ result = { status = 99, error = "out of memory"}
+ else
+ result = mpx:execute(format(preamble, replacesuffix(name,"mp")))
+ end
+ reporterror(result)
+ return mpx, result
+end
+
+% \end{macrocode}
+%
+% |plain| or |metafun|,
+% though we cannot support |metafun| format fully.
+% \begin{macrocode}
+local currentformat = "plain"
+
+local function setformat (name)
+ currentformat = name
+end
+luamplib.setformat = setformat
+
+% \end{macrocode}
+%
+% Here, excute each |mplibcode| data,
+% ie |\begin{mplibcode} ... \end{mplibcode}|.
+% \begin{macrocode}
+local function process_indeed (mpx, data)
+ local converted, result = false, {}
+ if mpx and data then
+ result = mpx:execute(data)
+ local log = reporterror(result)
+ if log then
+ if luamplib.showlog then
+ info("%s",luamplib.lastlog)
+ luamplibresetlastlog()
+ elseif result.fig then
+% \end{macrocode}
+%
+% v2.6.1: now luamplib does not disregard |show| command,
+% even when |luamplib.showlog| is false. Incidentally,
+% it does not raise error but just prints a warning,
+% even if output has no figure.
+% \begin{macrocode}
+ if log:find("\n>>") then info("%s",log) end
+ converted = luamplib.convert(result)
+ else
+ info("%s",log)
+ warn("No figure output. Maybe no beginfig/endfig")
+ end
+ end
+ else
+ err("Mem file unloadable. Maybe generated with a different version of mplib?")
+ end
+ return converted, result
+end
+
+% \end{macrocode}
+%
+% v2.9 has introduced the concept of ``code inherit''
+% \begin{macrocode}
+luamplib.codeinherit = false
+local mplibinstances = {}
+
+local function process (data)
+% \end{macrocode}
+%
+% The workaround of issue \#70 seems to be unnecessary, as we use
+% |make_text| now.
+% \begin{verbatim}
+% if not data:find(name_b.."beginfig%s*%([%+%-%s]*%d[%.%d%s]*%)") then
+% data = data .. "beginfig(-1);endfig;"
+% end
+% \end{verbatim}
+% \begin{macrocode}
+ local standalone = not luamplib.codeinherit
+ local currfmt = currentformat .. (luamplib.numbersystem or "scaled")
+ .. tostring(luamplib.textextlabel) .. tostring(luamplib.legacy_verbatimtex)
+ local mpx = mplibinstances[currfmt]
+ if mpx and standalone then
+ mpx:finish()
+ end
+ if standalone or not mpx then
+ mpx = luamplibload(currentformat)
+ mplibinstances[currfmt] = mpx
+ end
+ return process_indeed(mpx, data)
+end
+
+% \end{macrocode}
+%
+% |make_text| and some |run_script| uses \LuaTeX's |tex.runtoks|,
+% which made possible running \TeX\ code snippets inside |\directlua|.
+% \begin{macrocode}
+local catlatex = luatexbase.registernumber("catcodetable@latex")
+local catat11 = luatexbase.registernumber("catcodetable@atletter")
+
+% \end{macrocode}
+%
+% |tex.scantoks| sometimes fail to read catcode properly, especially
+% |\#|, |\&|, or |\%|. After some experiment, we dropped using it.
+% Instead, a function containing |tex.script| seems to work nicely.
+% \begin{verbatim}
+% local function run_tex_code_no_use (str, cat)
+% cat = cat or catlatex
+% texscantoks("mplibtmptoks", cat, str)
+% texruntoks("mplibtmptoks")
+% end
+% \end{verbatim}
+% \begin{macrocode}
+local function run_tex_code (str, cat)
+ cat = cat or catlatex
+ texruntoks(function() texsprint(cat, str) end)
+end
+
+% \end{macrocode}
+%
+% Indefinite number of boxes are needed for |btex ... etex|.
+% So starts at somewhat huge number of box registry. Of course,
+% this may conflict with other packages using many many boxes.
+% (When |codeinherit| feature is enabled, boxes must be globally defined.)
+% But I don't know any reliable way to escape this danger.
+% \begin{macrocode}
+local tex_box_id = 2047
+% \end{macrocode}
+%
+% For conversion of |sp| to |bp|.
+% \begin{macrocode}
+local factor = 65536*(7227/7200)
+
+local function process_tex_text (str)
+ if str then
+ tex_box_id = tex_box_id + 1
+ local global = luamplib.globaltextext and "\\global" or ""
+ run_tex_code(format("%s\\setbox%i\\hbox{%s}", global, tex_box_id, str))
+ local box = texgetbox(tex_box_id)
+ local wd = box.width / factor
+ local ht = box.height / factor
+ local dp = box.depth / factor
+ return format("image(addto currentpicture doublepath unitsquare "..
+ "xscaled %f yscaled %f shifted (0,-%f) "..
+ "withprescript \"mplibtexboxid=%i:%f:%f\")",
+ wd, ht+dp, dp, tex_box_id, wd, ht+dp)
+ end
+ return ""
+end
+
+% \end{macrocode}
+%
+% Make |color| or |xcolor|'s color expressions usable,
+% with \cs{mpcolor} or |mplibcolor|
+% \begin{macrocode}
+local function process_color (str)
+ if str then
+ if not str:find("{.-}") then
+ str = format("{%s}",str)
+ end
+ run_tex_code(format(
+ "\\def\\set@color{\\toks0\\expandafter{\\current@color}}\\color %s", str),
+ catat11)
+ return format("1 withprescript \"MPlibOverrideColor=%s\"", texgettoks(0))
+ end
+ return ""
+end
+
+% \end{macrocode}
+%
+% \cs{mpdim} is expanded before MPLib process, so code below will not be
+% used for |mplibcode| data. But who knows anyone would want it
+% in |.mp| input file. If then, you can say |mplibdimen(".5\textwidth")|
+% for example.
+% \begin{macrocode}
+local function process_dimen (str)
+ if str then
+ str = str:gsub("{(.+)}","%1")
+ run_tex_code(format("\\toks0\\expandafter{\\the\\dimexpr %s\\relax}", str))
+ return format("begingroup %s endgroup", texgettoks(0))
+ end
+ return ""
+end
+
+% \end{macrocode}
+%
+% Newly introduced method of processing |verbatimtex ... etex|.
+% Used when |\mpliblegacybehavior{false}| is declared.
+% \begin{macrocode}
+local function process_verbatimtex_text (str)
+ if str then
+ run_tex_code(str)
+ end
+ return ""
+end
+
+% \end{macrocode}
+%
+% For legacy verbatimtex process.
+% |verbatimtex ... etex| before |beginfig()| is not ignored,
+% but the \TeX\ code is inserted just before the mplib box. And
+% \TeX\ code inside |beginfig() ... endfig| is inserted after the mplib box.
+% \begin{macrocode}
+local tex_code_pre_mplib = {}
+luamplib.figid = 1
+luamplib.in_the_fig = false
+
+local function legacy_mplibcode_reset ()
+ tex_code_pre_mplib = {}
+ luamplib.figid = 1
+end
+
+local function process_verbatimtex_prefig (str)
+ if str then
+ tex_code_pre_mplib[luamplib.figid] = str
+ end
+ return ""
+end
+
+local function process_verbatimtex_infig (str)
+ if str then
+ return format("special \"postmplibverbtex=%s\";", str)
+ end
+ return ""
+end
+
+local runscript_funcs = {
+ luamplibtext = process_tex_text,
+ luamplibcolor = process_color,
+ luamplibdimen = process_dimen,
+ luamplibprefig = process_verbatimtex_prefig,
+ luamplibinfig = process_verbatimtex_infig,
+ luamplibverbtex = process_verbatimtex_text,
+}
+
+% \end{macrocode}
+%
+% For |metafun| format. see issue \#79.
+% \begin{macrocode}
+mp = mp or {}
+local mp = mp
+mp.mf_path_reset = mp.mf_path_reset or function() end
+mp.mf_finish_saving_data = mp.mf_finish_saving_data or function() end
+
+% \end{macrocode}
+%
+% A function from \ConTeXt\ general.
+% \begin{macrocode}
+local function mpprint(buffer,...)
+ for i=1,select("#",...) do
+ local value = select(i,...)
+ if value ~= nil then
+ local t = type(value)
+ if t == "number" then
+ buffer[#buffer+1] = format("%.16f",value)
+ elseif t == "string" then
+ buffer[#buffer+1] = value
+ elseif t == "table" then
+ buffer[#buffer+1] = "(" .. tableconcat(value,",") .. ")"
+ else -- boolean or whatever
+ buffer[#buffer+1] = tostring(value)
+ end
+ end
+ end
+end
+
+function luamplib.runscript (code)
+ local id, str = code:match("(.-){(.+)}")
+ if id and str and str ~= "" then
+ local f = runscript_funcs[id]
+ if f then
+ local t = f(str)
+ if t then return t end
+ end
+ end
+ local f = loadstring(code)
+ if type(f) == "function" then
+ local buffer = {}
+ function mp.print(...)
+ mpprint(buffer,...)
+ end
+ f()
+ return tableconcat(buffer,"")
+ end
+ return ""
+end
+
+% \end{macrocode}
+%
+% |make_text| must be one liner, so comment sign is not allowed.
+% \begin{macrocode}
+local function protecttexcontents (str)
+ return str:gsub("\\%%", "\0PerCent\0")
+ :gsub("%%.-\n", "")
+ :gsub("%%.-$", "")
+ :gsub("%zPerCent%z", "\\%%")
+ :gsub("%s+", " ")
+end
+
+luamplib.legacy_verbatimtex = true
+
+function luamplib.maketext (str, what)
+ if str and str ~= "" then
+ str = protecttexcontents(str)
+ if what == 1 then
+ if not str:find("\\documentclass"..name_e) and
+ not str:find("\\begin%s*{document}") and
+ not str:find("\\documentstyle"..name_e) and
+ not str:find("\\usepackage"..name_e) then
+ if luamplib.legacy_verbatimtex then
+ if luamplib.in_the_fig then
+ return process_verbatimtex_infig(str)
+ else
+ return process_verbatimtex_prefig(str)
+ end
+ else
+ return process_verbatimtex_text(str)
+ end
+ end
+ else
+ return process_tex_text(str)
+ end
+ end
+ return ""
+end
+
+% \end{macrocode}
+%
+% Our MetaPost preambles
+% \begin{macrocode}
+local mplibcodepreamble = [[
+texscriptmode := 2;
+def rawtextext (expr t) = runscript("luamplibtext{"&t&"}") enddef;
+def mplibcolor (expr t) = runscript("luamplibcolor{"&t&"}") enddef;
+def mplibdimen (expr t) = runscript("luamplibdimen{"&t&"}") enddef;
+def VerbatimTeX (expr t) = runscript("luamplibverbtex{"&t&"}") enddef;
+if known context_mlib:
+ defaultfont := "cmtt10";
+ let infont = normalinfont;
+ let fontsize = normalfontsize;
+ vardef thelabel@#(expr p,z) =
+ if string p :
+ thelabel@#(p infont defaultfont scaled defaultscale,z)
+ else :
+ p shifted (z + labeloffset*mfun_laboff@# -
+ (mfun_labxf@#*lrcorner p + mfun_labyf@#*ulcorner p +
+ (1-mfun_labxf@#-mfun_labyf@#)*llcorner p))
+ fi
+ enddef;
+ def graphictext primary filename =
+ if (readfrom filename = EOF):
+ errmessage "Please prepare '"&filename&"' in advance with"&
+ " 'pstoedit -ssp -dt -f mpost yourfile.ps "&filename&"'";
+ fi
+ closefrom filename;
+ def data_mpy_file = filename enddef;
+ mfun_do_graphic_text (filename)
+ enddef;
+else:
+ vardef textext@# (text t) = rawtextext (t) enddef;
+fi
+def externalfigure primary filename =
+ draw rawtextext("\includegraphics{"& filename &"}")
+enddef;
+def TEX = textext enddef;
+]]
+luamplib.mplibcodepreamble = mplibcodepreamble
+
+local legacyverbatimtexpreamble = [[
+def specialVerbatimTeX (text t) = runscript("luamplibprefig{"&t&"}") enddef;
+def normalVerbatimTeX (text t) = runscript("luamplibinfig{"&t&"}") enddef;
+let VerbatimTeX = specialVerbatimTeX;
+extra_beginfig := extra_beginfig & " let VerbatimTeX = normalVerbatimTeX;"&
+ "runscript(" &ditto& "luamplib.in_the_fig=true" &ditto& ");";
+extra_endfig := extra_endfig & " let VerbatimTeX = specialVerbatimTeX;"&
+ "runscript(" &ditto&
+ "luamplib.in_the_fig=false luamplib.figid=luamplib.figid+1" &ditto& ");";
+]]
+luamplib.legacyverbatimtexpreamble = legacyverbatimtexpreamble
+
+local textextlabelpreamble = [[
+primarydef s infont f = rawtextext(s) enddef;
+def fontsize expr f =
+ begingroup
+ save size; numeric size;
+ size := mplibdimen("1em");
+ if size = 0: 10pt else: size fi
+ endgroup
+enddef;
+]]
+luamplib.textextlabelpreamble = textextlabelpreamble
+
+% \end{macrocode}
+%
+% When \cs{mplibverbatim} is enabled, do not expand |mplibcode| data.
+% \begin{macrocode}
+luamplib.verbatiminput = false
+
+% \end{macrocode}
+%
+% Do not expand |btex ... etex|, |verbatimtex ... etex|, and
+% string expressions.
+% \begin{macrocode}
+local function protect_expansion (str)
+ if str then
+ str = str:gsub("\\","\1Control\1")
+ :gsub("%%","\1Comment\1")
+ :gsub("#", "\1HashSign\1")
+ :gsub("{", "\1LBrace\1")
+ :gsub("}", "\1RBrace\1")
+ return format("\\unexpanded{%s}",str)
+ end
+end
+
+local function unprotect_expansion (str)
+ if str then
+ return str:gsub("\1Control\1", "\\")
+ :gsub("\1Comment\1", "%%")
+ :gsub("\1HashSign\1","#")
+ :gsub("\1LBrace\1", "{")
+ :gsub("\1RBrace\1", "}")
+ end
+end
+
+local function process_mplibcode (data)
+% \end{macrocode}
+%
+% This is needed for legacy behavior regarding |verbatimtex|
+% \begin{macrocode}
+ legacy_mplibcode_reset()
+
+ local everymplib = texgettoks('everymplibtoks') or ''
+ local everyendmplib = texgettoks('everyendmplibtoks') or ''
+ data = format("\n%s\n%s\n%s\n",everymplib, data, everyendmplib)
+ data = data:gsub("\r","\n")
+
+ data = data:gsub("\\mpcolor%s+(.-%b{})","mplibcolor(\"%1\")")
+ data = data:gsub("\\mpdim%s+(%b{})", "mplibdimen(\"%1\")")
+ data = data:gsub("\\mpdim%s+(\\%a+)","mplibdimen(\"%1\")")
+
+ data = data:gsub(btex_etex, function(str)
+ return format("btex %s etex ", -- space
+ luamplib.verbatiminput and str or protect_expansion(str))
+ end)
+ data = data:gsub(verbatimtex_etex, function(str)
+ return format("verbatimtex %s etex;", -- semicolon
+ luamplib.verbatiminput and str or protect_expansion(str))
+ end)
+
+% \end{macrocode}
+%
+% If not |mplibverbatim|, expand |mplibcode| data,
+% so that users can use \TeX\ codes in it.
+% It has turned out that no comment sign is allowed.
+% \begin{macrocode}
+ if not luamplib.verbatiminput then
+ data = data:gsub("\".-\"", protect_expansion)
+ data = data:gsub("%%.-\n","")
+ run_tex_code(format("\\toks0\\expanded{{%s}}",data))
+ data = texgettoks(0)
+% \end{macrocode}
+%
+% Next line to address issue \#55
+% \begin{macrocode}
+ data = data:gsub("##", "#")
+ data = data:gsub("\".-\"", unprotect_expansion)
+ data = data:gsub(btex_etex, function(str)
+ return format("btex %s etex", unprotect_expansion(str))
+ end)
+ data = data:gsub(verbatimtex_etex, function(str)
+ return format("verbatimtex %s etex", unprotect_expansion(str))
+ end)
+ end
+
+ process(data)
+end
+luamplib.process_mplibcode = process_mplibcode
+
+% \end{macrocode}
+%
+% For parsing |prescript| materials.
+% \begin{macrocode}
+local further_split_keys = {
+ ["mplibtexboxid"] = true,
+ ["sh_color_a"] = true,
+ ["sh_color_b"] = true,
+}
+
+local function script2table(s)
+ local t = {}
+ for _,i in ipairs(s:explode("\13+")) do
+ local k,v = i:match("(.-)=(.*)") -- v may contain = or empty.
+ if k and v and k ~= "" then
+ if further_split_keys[k] then
+ t[k] = v:explode(":")
+ else
+ t[k] = v
+ end
+ end
+ end
+ return t
+end
+
+% \end{macrocode}
+%
+% Codes below for inserting PDF lieterals are mostly from ConTeXt general,
+% with small changes when needed.
+% \begin{macrocode}
+local function getobjects(result,figure,f)
+ return figure:objects()
+end
+
+local function convert(result, flusher)
+ luamplib.flush(result, flusher)
+ return true -- done
+end
+luamplib.convert = convert
+
+local function pdf_startfigure(n,llx,lly,urx,ury)
+ texsprint(format("\\mplibstarttoPDF{%f}{%f}{%f}{%f}",llx,lly,urx,ury))
+end
+
+local function pdf_stopfigure()
+ texsprint("\\mplibstoptoPDF")
+end
+
+% \end{macrocode}
+%
+% |tex.tprint| with catcode regime -2, as sometimes |#| gets doubled
+% in the argument of pdfliteral.
+% \begin{macrocode}
+local function pdf_literalcode(fmt,...) -- table
+ textprint({"\\mplibtoPDF{"},{-2,format(fmt,...)},{"}"})
+end
+
+local function pdf_textfigure(font,size,text,width,height,depth)
+ text = text:gsub(".",function(c)
+ return format("\\hbox{\\char%i}",string.byte(c)) -- kerning happens in metapost
+ end)
+ texsprint(format("\\mplibtextext{%s}{%f}{%s}{%s}{%f}",font,size,text,0,-( 7200/ 7227)/65536*depth))
+end
+
+local bend_tolerance = 131/65536
+
+local rx, sx, sy, ry, tx, ty, divider = 1, 0, 0, 1, 0, 0, 1
+
+local function pen_characteristics(object)
+ local t = mplib.pen_info(object)
+ rx, ry, sx, sy, tx, ty = t.rx, t.ry, t.sx, t.sy, t.tx, t.ty
+ divider = sx*sy - rx*ry
+ return not (sx==1 and rx==0 and ry==0 and sy==1 and tx==0 and ty==0), t.width
+end
+
+local function concat(px, py) -- no tx, ty here
+ return (sy*px-ry*py)/divider,(sx*py-rx*px)/divider
+end
+
+local function curved(ith,pth)
+ local d = pth.left_x - ith.right_x
+ if abs(ith.right_x - ith.x_coord - d) <= bend_tolerance and abs(pth.x_coord - pth.left_x - d) <= bend_tolerance then
+ d = pth.left_y - ith.right_y
+ if abs(ith.right_y - ith.y_coord - d) <= bend_tolerance and abs(pth.y_coord - pth.left_y - d) <= bend_tolerance then
+ return false
+ end
+ end
+ return true
+end
+
+local function flushnormalpath(path,open)
+ local pth, ith
+ for i=1,#path do
+ pth = path[i]
+ if not ith then
+ pdf_literalcode("%f %f m",pth.x_coord,pth.y_coord)
+ elseif curved(ith,pth) then
+ pdf_literalcode("%f %f %f %f %f %f c",ith.right_x,ith.right_y,pth.left_x,pth.left_y,pth.x_coord,pth.y_coord)
+ else
+ pdf_literalcode("%f %f l",pth.x_coord,pth.y_coord)
+ end
+ ith = pth
+ end
+ if not open then
+ local one = path[1]
+ if curved(pth,one) then
+ pdf_literalcode("%f %f %f %f %f %f c",pth.right_x,pth.right_y,one.left_x,one.left_y,one.x_coord,one.y_coord )
+ else
+ pdf_literalcode("%f %f l",one.x_coord,one.y_coord)
+ end
+ elseif #path == 1 then -- special case .. draw point
+ local one = path[1]
+ pdf_literalcode("%f %f l",one.x_coord,one.y_coord)
+ end
+end
+
+local function flushconcatpath(path,open)
+ pdf_literalcode("%f %f %f %f %f %f cm", sx, rx, ry, sy, tx ,ty)
+ local pth, ith
+ for i=1,#path do
+ pth = path[i]
+ if not ith then
+ pdf_literalcode("%f %f m",concat(pth.x_coord,pth.y_coord))
+ elseif curved(ith,pth) then
+ local a, b = concat(ith.right_x,ith.right_y)
+ local c, d = concat(pth.left_x,pth.left_y)
+ pdf_literalcode("%f %f %f %f %f %f c",a,b,c,d,concat(pth.x_coord, pth.y_coord))
+ else
+ pdf_literalcode("%f %f l",concat(pth.x_coord, pth.y_coord))
+ end
+ ith = pth
+ end
+ if not open then
+ local one = path[1]
+ if curved(pth,one) then
+ local a, b = concat(pth.right_x,pth.right_y)
+ local c, d = concat(one.left_x,one.left_y)
+ pdf_literalcode("%f %f %f %f %f %f c",a,b,c,d,concat(one.x_coord, one.y_coord))
+ else
+ pdf_literalcode("%f %f l",concat(one.x_coord,one.y_coord))
+ end
+ elseif #path == 1 then -- special case .. draw point
+ local one = path[1]
+ pdf_literalcode("%f %f l",concat(one.x_coord,one.y_coord))
+ end
+end
+
+% \end{macrocode}
+%
+% |dvipdfmx| is supported, though nobody seems to use it.
+% \begin{macrocode}
+local pdfoutput = tonumber(texget("outputmode")) or tonumber(texget("pdfoutput"))
+local pdfmode = pdfoutput > 0
+
+local function start_pdf_code()
+ if pdfmode then
+ pdf_literalcode("q")
+ else
+ texsprint("\\special{pdf:bcontent}") -- dvipdfmx
+ end
+end
+local function stop_pdf_code()
+ if pdfmode then
+ pdf_literalcode("Q")
+ else
+ texsprint("\\special{pdf:econtent}") -- dvipdfmx
+ end
+end
+
+% \end{macrocode}
+%
+% Now we process hboxes created from |btex ... etex| or
+% |textext(...)| or |TEX(...)|, all being the same internally.
+% \begin{macrocode}
+local function put_tex_boxes (object,prescript)
+ local box = prescript.mplibtexboxid
+ local n,tw,th = box[1],tonumber(box[2]),tonumber(box[3])
+ if n and tw and th then
+ local op = object.path
+ local first, second, fourth = op[1], op[2], op[4]
+ local tx, ty = first.x_coord, first.y_coord
+ local sx, rx, ry, sy = 1, 0, 0, 1
+ if tw ~= 0 then
+ sx = (second.x_coord - tx)/tw
+ rx = (second.y_coord - ty)/tw
+ if sx == 0 then sx = 0.00001 end
+ end
+ if th ~= 0 then
+ sy = (fourth.y_coord - ty)/th
+ ry = (fourth.x_coord - tx)/th
+ if sy == 0 then sy = 0.00001 end
+ end
+ start_pdf_code()
+ pdf_literalcode("%f %f %f %f %f %f cm",sx,rx,ry,sy,tx,ty)
+ texsprint(format("\\mplibputtextbox{%i}",n))
+ stop_pdf_code()
+ end
+end
+
+% \end{macrocode}
+%
+% Colors and Transparency
+% \begin{macrocode}
+local pdf_objs = {}
+local token, getpageres, setpageres = newtoken or token
+local pgf = { bye = "pgfutil@everybye", extgs = "pgf@sys@addpdfresource@extgs@plain" }
+
+if pdfmode then -- repect luaotfload-colors
+ getpageres = pdf.getpageresources or function() return pdf.pageresources end
+ setpageres = pdf.setpageresources or function(s) pdf.pageresources = s end
+else
+ texsprint("\\special{pdf:obj @MPlibTr<<>>}",
+ "\\special{pdf:obj @MPlibSh<<>>}")
+end
+
+local function update_pdfobjs (os)
+ local on = pdf_objs[os]
+ if on then
+ return on,false
+ end
+ if pdfmode then
+ on = pdf.immediateobj(os)
+ else
+ on = pdf_objs.cnt or 0
+ pdf_objs.cnt = on + 1
+ end
+ pdf_objs[os] = on
+ return on,true
+end
+
+local transparancy_modes = { [0] = "Normal",
+ "Normal", "Multiply", "Screen", "Overlay",
+ "SoftLight", "HardLight", "ColorDodge", "ColorBurn",
+ "Darken", "Lighten", "Difference", "Exclusion",
+ "Hue", "Saturation", "Color", "Luminosity",
+ "Compatible",
+}
+
+local function update_tr_res(res,mode,opaq)
+ local os = format("<</BM /%s/ca %.3f/CA %.3f/AIS false>>",mode,opaq,opaq)
+ local on, new = update_pdfobjs(os)
+ if new then
+ if pdfmode then
+ res = format("%s/MPlibTr%i %i 0 R",res,on,on)
+ else
+ if pgf.loaded then
+ texsprint(format("\\csname %s\\endcsname{/MPlibTr%i%s}", pgf.extgs, on, os))
+ else
+ texsprint(format("\\special{pdf:put @MPlibTr<</MPlibTr%i%s>>}",on,os))
+ end
+ end
+ end
+ return res,on
+end
+
+local function tr_pdf_pageresources(mode,opaq)
+ if token and pgf.bye and not pgf.loaded then
+ pgf.loaded = token.create(pgf.bye).cmdname == "assign_toks"
+ pgf.bye = pgf.loaded and pgf.bye
+ end
+ local res, on_on, off_on = "", nil, nil
+ res, off_on = update_tr_res(res, "Normal", 1)
+ res, on_on = update_tr_res(res, mode, opaq)
+ if pdfmode then
+ if res ~= "" then
+ if pgf.loaded then
+ texsprint(format("\\csname %s\\endcsname{%s}", pgf.extgs, res))
+ else
+ local tpr, n = getpageres() or "", 0
+ tpr, n = tpr:gsub("/ExtGState<<", "%1"..res)
+ if n == 0 then
+ tpr = format("%s/ExtGState<<%s>>", tpr, res)
+ end
+ setpageres(tpr)
+ end
+ end
+ else
+ if not pgf.loaded then
+ texsprint(format("\\special{pdf:put @resources<</ExtGState @MPlibTr>>}"))
+ end
+ end
+ return on_on, off_on
+end
+
+% \end{macrocode}
+%
+% Shading with |metafun| format. (maybe legacy way)
+% \begin{macrocode}
+local shading_res
+
+local function shading_initialize ()
+ shading_res = {}
+ if pdfmode and luatexbase.callbacktypes.finish_pdffile then -- ltluatex
+ local shading_obj = pdf.reserveobj()
+ setpageres(format("%s/Shading %i 0 R",getpageres() or "",shading_obj))
+ luatexbase.add_to_callback("finish_pdffile", function()
+ pdf.immediateobj(shading_obj,format("<<%s>>",tableconcat(shading_res)))
+ end, "luamplib.finish_pdffile")
+ pdf_objs.finishpdf = true
+ end
+end
+
+local function sh_pdfpageresources(shtype,domain,colorspace,colora,colorb,coordinates)
+ if not shading_res then shading_initialize() end
+ local os = format("<</FunctionType 2/Domain [ %s ]/C0 [ %s ]/C1 [ %s ]/N 1>>",
+ domain, colora, colorb)
+ local funcobj = pdfmode and format("%i 0 R",update_pdfobjs(os)) or os
+ os = format("<</ShadingType %i/ColorSpace /%s/Function %s/Coords [ %s ]/Extend [ true true ]/AntiAlias true>>",
+ shtype, colorspace, funcobj, coordinates)
+ local on, new = update_pdfobjs(os)
+ if pdfmode then
+ if new then
+ local res = format("/MPlibSh%i %i 0 R", on, on)
+ if pdf_objs.finishpdf then
+ shading_res[#shading_res+1] = res
+ else
+ local pageres = getpageres() or ""
+ if not pageres:find("/Shading<<.*>>") then
+ pageres = pageres.."/Shading<<>>"
+ end
+ pageres = pageres:gsub("/Shading<<","%1"..res)
+ setpageres(pageres)
+ end
+ end
+ else
+ if new then
+ texsprint(format("\\special{pdf:put @MPlibSh<</MPlibSh%i%s>>}",on,os))
+ end
+ texsprint(format("\\special{pdf:put @resources<</Shading @MPlibSh>>}"))
+ end
+ return on
+end
+
+local function color_normalize(ca,cb)
+ if #cb == 1 then
+ if #ca == 4 then
+ cb[1], cb[2], cb[3], cb[4] = 0, 0, 0, 1-cb[1]
+ else -- #ca = 3
+ cb[1], cb[2], cb[3] = cb[1], cb[1], cb[1]
+ end
+ elseif #cb == 3 then -- #ca == 4
+ cb[1], cb[2], cb[3], cb[4] = 1-cb[1], 1-cb[2], 1-cb[3], 0
+ end
+end
+
+local prev_override_color
+
+local function do_preobj_color(object,prescript)
+% \end{macrocode}
+%
+% transparency
+% \begin{macrocode}
+ local opaq = prescript and prescript.tr_transparency
+ local tron_no, troff_no
+ if opaq then
+ local mode = prescript.tr_alternative or 1
+ mode = transparancy_modes[tonumber(mode)]
+ tron_no, troff_no = tr_pdf_pageresources(mode,opaq)
+ pdf_literalcode("/MPlibTr%i gs",tron_no)
+ end
+% \end{macrocode}
+%
+% color
+% \begin{macrocode}
+ local override = prescript and prescript.MPlibOverrideColor
+ if override then
+ if pdfmode then
+ pdf_literalcode(override)
+ override = nil
+ else
+ texsprint(format("\\special{color push %s}",override))
+ prev_override_color = override
+ end
+ else
+ local cs = object.color
+ if cs and #cs > 0 then
+ pdf_literalcode(luamplib.colorconverter(cs))
+ prev_override_color = nil
+ elseif not pdfmode then
+ override = prev_override_color
+ if override then
+ texsprint(format("\\special{color push %s}",override))
+ end
+ end
+ end
+% \end{macrocode}
+%
+% shading
+% \begin{macrocode}
+ local sh_type = prescript and prescript.sh_type
+ if sh_type then
+ local domain = prescript.sh_domain
+ local centera = prescript.sh_center_a:explode()
+ local centerb = prescript.sh_center_b:explode()
+ for _,t in pairs({centera,centerb}) do
+ for i,v in ipairs(t) do
+ t[i] = format("%f",v)
+ end
+ end
+ centera = tableconcat(centera," ")
+ centerb = tableconcat(centerb," ")
+ local colora = prescript.sh_color_a or {0};
+ local colorb = prescript.sh_color_b or {1};
+ for _,t in pairs({colora,colorb}) do
+ for i,v in ipairs(t) do
+ t[i] = format("%.3f",v)
+ end
+ end
+ if #colora > #colorb then
+ color_normalize(colora,colorb)
+ elseif #colorb > #colora then
+ color_normalize(colorb,colora)
+ end
+ local colorspace
+ if #colorb == 1 then colorspace = "DeviceGray"
+ elseif #colorb == 3 then colorspace = "DeviceRGB"
+ elseif #colorb == 4 then colorspace = "DeviceCMYK"
+ else return troff_no,override
+ end
+ colora = tableconcat(colora, " ")
+ colorb = tableconcat(colorb, " ")
+ local shade_no
+ if sh_type == "linear" then
+ local coordinates = tableconcat({centera,centerb}," ")
+ shade_no = sh_pdfpageresources(2,domain,colorspace,colora,colorb,coordinates)
+ elseif sh_type == "circular" then
+ local radiusa = format("%f",prescript.sh_radius_a)
+ local radiusb = format("%f",prescript.sh_radius_b)
+ local coordinates = tableconcat({centera,radiusa,centerb,radiusb}," ")
+ shade_no = sh_pdfpageresources(3,domain,colorspace,colora,colorb,coordinates)
+ end
+ pdf_literalcode("q /Pattern cs")
+ return troff_no,override,shade_no
+ end
+ return troff_no,override
+end
+
+local function do_postobj_color(tr,over,sh)
+ if sh then
+ pdf_literalcode("W n /MPlibSh%s sh Q",sh)
+ end
+ if over then
+ texsprint("\\special{color pop}")
+ end
+ if tr then
+ pdf_literalcode("/MPlibTr%i gs",tr)
+ end
+end
+
+% \end{macrocode}
+%
+% Finally, flush figures by inserting PDF literals.
+% \begin{macrocode}
+local function flush(result,flusher)
+ if result then
+ local figures = result.fig
+ if figures then
+ for f=1, #figures do
+ info("flushing figure %s",f)
+ local figure = figures[f]
+ local objects = getobjects(result,figure,f)
+ local fignum = tonumber(figure:filename():match("([%d]+)$") or figure:charcode() or 0)
+ local miterlimit, linecap, linejoin, dashed = -1, -1, -1, false
+ local bbox = figure:boundingbox()
+ local llx, lly, urx, ury = bbox[1], bbox[2], bbox[3], bbox[4] -- faster than unpack
+ if urx < llx then
+% \end{macrocode}
+%
+% luamplib silently ignores this invalid figure for those
+% that do not contain |beginfig ... endfig|. (issue \#70)
+% Original code of ConTeXt general was:
+% \begin{verbatim}
+% -- invalid
+% pdf_startfigure(fignum,0,0,0,0)
+% pdf_stopfigure()
+% \end{verbatim}
+% \begin{macrocode}
+ else
+% \end{macrocode}
+%
+% For legacy behavior. Insert `pre-fig' \TeX\ code here, and
+% prepare a table for `in-fig' codes.
+% \begin{macrocode}
+ if tex_code_pre_mplib[f] then
+ texsprint(tex_code_pre_mplib[f])
+ end
+ local TeX_code_bot = {}
+ pdf_startfigure(fignum,llx,lly,urx,ury)
+ start_pdf_code()
+ if objects then
+ local savedpath = nil
+ local savedhtap = nil
+ for o=1,#objects do
+ local object = objects[o]
+ local objecttype = object.type
+% \end{macrocode}
+%
+% The following 5 lines are part of |btex...etex| patch.
+% Again, colors are processed at this stage.
+% \begin{macrocode}
+ local prescript = object.prescript
+ prescript = prescript and script2table(prescript) -- prescript is now a table
+ local tr_opaq,cr_over,shade_no = do_preobj_color(object,prescript)
+ if prescript and prescript.mplibtexboxid then
+ put_tex_boxes(object,prescript)
+ elseif objecttype == "start_bounds" or objecttype == "stop_bounds" then --skip
+ elseif objecttype == "start_clip" then
+ local evenodd = not object.istext and object.postscript == "evenodd"
+ start_pdf_code()
+ flushnormalpath(object.path,false)
+ pdf_literalcode(evenodd and "W* n" or "W n")
+ elseif objecttype == "stop_clip" then
+ stop_pdf_code()
+ miterlimit, linecap, linejoin, dashed = -1, -1, -1, false
+ elseif objecttype == "special" then
+% \end{macrocode}
+%
+% Collect \TeX\ codes that will be executed after flushing.
+% Legacy behavior.
+% \begin{macrocode}
+ if prescript and prescript.postmplibverbtex then
+ TeX_code_bot[#TeX_code_bot+1] = prescript.postmplibverbtex
+ end
+ elseif objecttype == "text" then
+ local ot = object.transform -- 3,4,5,6,1,2
+ start_pdf_code()
+ pdf_literalcode("%f %f %f %f %f %f cm",ot[3],ot[4],ot[5],ot[6],ot[1],ot[2])
+ pdf_textfigure(object.font,object.dsize,object.text,object.width,object.height,object.depth)
+ stop_pdf_code()
+ else
+ local evenodd, collect, both = false, false, false
+ local postscript = object.postscript
+ if not object.istext then
+ if postscript == "evenodd" then
+ evenodd = true
+ elseif postscript == "collect" then
+ collect = true
+ elseif postscript == "both" then
+ both = true
+ elseif postscript == "eoboth" then
+ evenodd = true
+ both = true
+ end
+ end
+ if collect then
+ if not savedpath then
+ savedpath = { object.path or false }
+ savedhtap = { object.htap or false }
+ else
+ savedpath[#savedpath+1] = object.path or false
+ savedhtap[#savedhtap+1] = object.htap or false
+ end
+ else
+ local ml = object.miterlimit
+ if ml and ml ~= miterlimit then
+ miterlimit = ml
+ pdf_literalcode("%f M",ml)
+ end
+ local lj = object.linejoin
+ if lj and lj ~= linejoin then
+ linejoin = lj
+ pdf_literalcode("%i j",lj)
+ end
+ local lc = object.linecap
+ if lc and lc ~= linecap then
+ linecap = lc
+ pdf_literalcode("%i J",lc)
+ end
+ local dl = object.dash
+ if dl then
+ local d = format("[%s] %f d",tableconcat(dl.dashes or {}," "),dl.offset)
+ if d ~= dashed then
+ dashed = d
+ pdf_literalcode(dashed)
+ end
+ elseif dashed then
+ pdf_literalcode("[] 0 d")
+ dashed = false
+ end
+ local path = object.path
+ local transformed, penwidth = false, 1
+ local open = path and path[1].left_type and path[#path].right_type
+ local pen = object.pen
+ if pen then
+ if pen.type == 'elliptical' then
+ transformed, penwidth = pen_characteristics(object) -- boolean, value
+ pdf_literalcode("%f w",penwidth)
+ if objecttype == 'fill' then
+ objecttype = 'both'
+ end
+ else -- calculated by mplib itself
+ objecttype = 'fill'
+ end
+ end
+ if transformed then
+ start_pdf_code()
+ end
+ if path then
+ if savedpath then
+ for i=1,#savedpath do
+ local path = savedpath[i]
+ if transformed then
+ flushconcatpath(path,open)
+ else
+ flushnormalpath(path,open)
+ end
+ end
+ savedpath = nil
+ end
+ if transformed then
+ flushconcatpath(path,open)
+ else
+ flushnormalpath(path,open)
+ end
+% \end{macrocode}
+%
+% Change from ConTeXt general: there was color stuffs.
+% \begin{macrocode}
+ if not shade_no then -- conflict with shading
+ if objecttype == "fill" then
+ pdf_literalcode(evenodd and "h f*" or "h f")
+ elseif objecttype == "outline" then
+ if both then
+ pdf_literalcode(evenodd and "h B*" or "h B")
+ else
+ pdf_literalcode(open and "S" or "h S")
+ end
+ elseif objecttype == "both" then
+ pdf_literalcode(evenodd and "h B*" or "h B")
+ end
+ end
+ end
+ if transformed then
+ stop_pdf_code()
+ end
+ local path = object.htap
+ if path then
+ if transformed then
+ start_pdf_code()
+ end
+ if savedhtap then
+ for i=1,#savedhtap do
+ local path = savedhtap[i]
+ if transformed then
+ flushconcatpath(path,open)
+ else
+ flushnormalpath(path,open)
+ end
+ end
+ savedhtap = nil
+ evenodd = true
+ end
+ if transformed then
+ flushconcatpath(path,open)
+ else
+ flushnormalpath(path,open)
+ end
+ if objecttype == "fill" then
+ pdf_literalcode(evenodd and "h f*" or "h f")
+ elseif objecttype == "outline" then
+ pdf_literalcode(open and "S" or "h S")
+ elseif objecttype == "both" then
+ pdf_literalcode(evenodd and "h B*" or "h B")
+ end
+ if transformed then
+ stop_pdf_code()
+ end
+ end
+ end
+ end
+% \end{macrocode}
+%
+% Added to ConTeXt general: color stuff.
+% And execute legacy |verbatimtex| code.
+% \begin{macrocode}
+ do_postobj_color(tr_opaq,cr_over,shade_no)
+ end
+ end
+ stop_pdf_code()
+ pdf_stopfigure()
+ if #TeX_code_bot > 0 then texsprint(TeX_code_bot) end
+ end
+ end
+ end
+ end
+end
+luamplib.flush = flush
+
+local function colorconverter(cr)
+ local n = #cr
+ if n == 4 then
+ local c, m, y, k = cr[1], cr[2], cr[3], cr[4]
+ return format("%.3f %.3f %.3f %.3f k %.3f %.3f %.3f %.3f K",c,m,y,k,c,m,y,k), "0 g 0 G"
+ elseif n == 3 then
+ local r, g, b = cr[1], cr[2], cr[3]
+ return format("%.3f %.3f %.3f rg %.3f %.3f %.3f RG",r,g,b,r,g,b), "0 g 0 G"
+ else
+ local s = cr[1]
+ return format("%.3f g %.3f G",s,s), "0 g 0 G"
+ end
+end
+luamplib.colorconverter = colorconverter
+% \end{macrocode}
+%
+% \iffalse
+%</lua>
+% \fi
+%
+% \subsection{\texorpdfstring{\TeX}{TeX} package}
+%
+%
+% \iffalse
+%<*package>
+% \fi
+%
+% First we need to load some packages.
+%
+% \begin{macrocode}
+\bgroup\expandafter\expandafter\expandafter\egroup
+\expandafter\ifx\csname selectfont\endcsname\relax
+ \input ltluatex
+\else
+ \NeedsTeXFormat{LaTeX2e}
+ \ProvidesPackage{luamplib}
+ [2019/03/26 v2.20.1 mplib package for LuaTeX]
+ \ifx\newluafunction\@undefined
+ \input ltluatex
+ \fi
+\fi
+% \end{macrocode}
+%
+% Loading of lua code.
+% \begin{macrocode}
+\directlua{require("luamplib")}
+% \end{macrocode}
+%
+% Support older engine. Seems we don't need it, but no harm.
+% \begin{macrocode}
+\ifx\scantextokens\undefined
+ \let\scantextokens\luatexscantextokens
+\fi
+\ifx\pdfoutput\undefined
+ \let\pdfoutput\outputmode
+ \protected\def\pdfliteral{\pdfextension literal}
+\fi
+% \end{macrocode}
+%
+% Set the format for metapost.
+% \begin{macrocode}
+\def\mplibsetformat#1{\directlua{luamplib.setformat("#1")}}
+% \end{macrocode}
+%
+% luamplib works in both PDF and DVI mode,
+% but only DVIPDFMx is supported currently among a number of DVI tools.
+% So we output a warning.
+% \begin{macrocode}
+\ifnum\pdfoutput>0
+ \let\mplibtoPDF\pdfliteral
+\else
+ \def\mplibtoPDF#1{\special{pdf:literal direct #1}}
+ \ifcsname PackageWarning\endcsname
+ \PackageWarning{luamplib}{take dvipdfmx path, no support for other dvi tools currently.}
+ \else
+ \write128{}
+ \write128{luamplib Warning: take dvipdfmx path, no support for other dvi tools currently.}
+ \write128{}
+ \fi
+\fi
+% \end{macrocode}
+%
+% Make |mplibcode| typesetted always in horizontal mode.
+% \begin{macrocode}
+\def\mplibforcehmode{\let\mplibhmodeornot\leavevmode}
+\def\mplibnoforcehmode{\let\mplibhmodeornot\relax}
+\mplibnoforcehmode
+% \end{macrocode}
+%
+% Catcode. We want to allow comment sign in |mplibcode|.
+% \begin{macrocode}
+\def\mplibsetupcatcodes{%
+ \mplibhmodeornot %catcode`\{=12 %catcode`\}=12
+ \catcode`\#=12 \catcode`\^=12 \catcode`\~=12 \catcode`\_=12
+ \catcode`\&=12 \catcode`\$=12 \catcode`\%=12 \catcode`\^^M=12 \endlinechar=10
+}
+% \end{macrocode}
+%
+% Make |btex...etex| box zero-metric.
+% \begin{macrocode}
+\def\mplibputtextbox#1{\vbox to 0pt{\vss\hbox to 0pt{\raise\dp#1\copy#1\hss}}}
+% \end{macrocode}
+%
+% As we have changed |^^J| catcode, the last line containing
+% |\end{mplibcode}| has |\n| at the end. Replace it with |^^M|.
+% \begin{macrocode}
+\newcount\mplibstartlineno
+\def\mplibpostmpcatcodes{%
+ \catcode`\{=12 \catcode`\}=12 \catcode`\#=12 \catcode`\%=12 }
+\def\mplibreplacenewlinebr{%
+ \begingroup \mplibpostmpcatcodes \mplibdoreplacenewlinebr}
+\begingroup\lccode`\~=`\^^M \lowercase{\endgroup
+ \def\mplibdoreplacenewlinebr#1^^J{\endgroup\scantextokens{{}#1~}}}
+% \end{macrocode}
+%
+% The Plain-specific stuff.
+% \begin{macrocode}
+\bgroup\expandafter\expandafter\expandafter\egroup
+\expandafter\ifx\csname selectfont\endcsname\relax
+\def\mplibreplacenewlinecs{%
+ \begingroup \mplibpostmpcatcodes \mplibdoreplacenewlinecs}
+\begingroup\lccode`\~=`\^^M \lowercase{\endgroup
+ \def\mplibdoreplacenewlinecs#1^^J{\endgroup\scantextokens{\relax#1~}}}
+\def\mplibcode{%
+ \mplibstartlineno\inputlineno
+ \begingroup
+ \begingroup
+ \mplibsetupcatcodes
+ \mplibdocode
+}
+\long\def\mplibdocode#1\endmplibcode{%
+ \endgroup
+ \directlua{luamplib.process_mplibcode([===[\unexpanded{#1}]===])}%
+ \endgroup
+ \ifnum\mplibstartlineno<\inputlineno\expandafter\mplibreplacenewlinecs\fi
+}
+\else
+% \end{macrocode}
+%
+% The \LaTeX-specific part: a new environment.
+% \begin{macrocode}
+\newenvironment{mplibcode}{%
+ \global\mplibstartlineno\inputlineno
+ \toks@{}\ltxdomplibcode
+}{}
+\def\ltxdomplibcode{%
+ \begingroup
+ \mplibsetupcatcodes
+ \ltxdomplibcodeindeed
+}
+\def\mplib@mplibcode{mplibcode}
+\long\def\ltxdomplibcodeindeed#1\end#2{%
+ \endgroup
+ \toks@\expandafter{\the\toks@#1}%
+ \def\mplibtemp@a{#2}%
+ \ifx\mplib@mplibcode\mplibtemp@a
+ \directlua{luamplib.process_mplibcode([===[\the\toks@]===])}%
+ \end{mplibcode}%
+ \ifnum\mplibstartlineno<\inputlineno
+ \expandafter\expandafter\expandafter\mplibreplacenewlinebr
+ \fi
+ \else
+ \toks@\expandafter{\the\toks@\end{#2}}\expandafter\ltxdomplibcode
+ \fi
+}
+\fi
+% \end{macrocode}
+%
+% User settings.
+% \begin{macrocode}
+\def\mpliblegacybehavior#1{\directlua{
+ local s = string.lower("#1")
+ if s == "enable" or s == "true" or s == "yes" then
+ luamplib.legacy_verbatimtex = true
+ else
+ luamplib.legacy_verbatimtex = false
+ end
+}}
+\def\mplibverbatim#1{\directlua{
+ local s = string.lower("#1")
+ if s == "enable" or s == "true" or s == "yes" then
+ luamplib.verbatiminput = true
+ else
+ luamplib.verbatiminput = false
+ end
+}}
+% \end{macrocode}
+%
+% \cs{everymplib} \& \cs{everyendmplib}: macros redefining
+% \cs{everymplibtoks} \& \cs{everyendmplibtoks} respectively
+% \begin{macrocode}
+\newtoks\mplibtmptoks
+\newtoks\everymplibtoks
+\newtoks\everyendmplibtoks
+\protected\def\everymplib{%
+ \mplibstartlineno\inputlineno
+ \begingroup
+ \mplibsetupcatcodes
+ \mplibdoeverymplib
+}
+\long\def\mplibdoeverymplib#1{%
+ \endgroup
+ \everymplibtoks{#1}%
+ \ifnum\mplibstartlineno<\inputlineno\expandafter\mplibreplacenewlinebr\fi
+}
+\protected\def\everyendmplib{%
+ \mplibstartlineno\inputlineno
+ \begingroup
+ \mplibsetupcatcodes
+ \mplibdoeveryendmplib
+}
+\long\def\mplibdoeveryendmplib#1{%
+ \endgroup
+ \everyendmplibtoks{#1}%
+ \ifnum\mplibstartlineno<\inputlineno\expandafter\mplibreplacenewlinebr\fi
+}
+% \end{macrocode}
+%
+% Allow \TeX\ dimen macros in |mplibcode|. But now |runscript| does the job.
+% \begin{verbatim}
+% \def\mpdim#1{ begingroup \the\dimexpr #1\relax\space endgroup }% gmp.sty
+% \end{verbatim}
+%
+% MPLib's number system. Now |binary| has gone away.
+% \begin{macrocode}
+\def\mplibnumbersystem#1{\directlua{
+ local t = "#1"
+ if t == "binary" then t = "decimal" end
+ luamplib.numbersystem = t
+}}
+% \end{macrocode}
+%
+% Settings for |.mp| cache files.
+% \begin{macrocode}
+\def\mplibmakenocache#1{\mplibdomakenocache #1,*,}
+\def\mplibdomakenocache#1,{%
+ \ifx\empty#1\empty
+ \expandafter\mplibdomakenocache
+ \else
+ \ifx*#1\else
+ \directlua{luamplib.noneedtoreplace["#1.mp"]=true}%
+ \expandafter\expandafter\expandafter\mplibdomakenocache
+ \fi
+ \fi
+}
+\def\mplibcancelnocache#1{\mplibdocancelnocache #1,*,}
+\def\mplibdocancelnocache#1,{%
+ \ifx\empty#1\empty
+ \expandafter\mplibdocancelnocache
+ \else
+ \ifx*#1\else
+ \directlua{luamplib.noneedtoreplace["#1.mp"]=false}%
+ \expandafter\expandafter\expandafter\mplibdocancelnocache
+ \fi
+ \fi
+}
+\def\mplibcachedir#1{\directlua{luamplib.getcachedir("\unexpanded{#1}")}}
+% \end{macrocode}
+%
+% More user settings.
+% \begin{macrocode}
+\def\mplibtextextlabel#1{\directlua{
+ local s = string.lower("#1")
+ if s == "enable" or s == "true" or s == "yes" then
+ luamplib.textextlabel = true
+ else
+ luamplib.textextlabel = false
+ end
+}}
+\def\mplibcodeinherit#1{\directlua{
+ local s = string.lower("#1")
+ if s == "enable" or s == "true" or s == "yes" then
+ luamplib.codeinherit = true
+ else
+ luamplib.codeinherit = false
+ end
+}}
+\def\mplibglobaltextext#1{\directlua{
+ local s = string.lower("#1")
+ if s == "enable" or s == "true" or s == "yes" then
+ luamplib.globaltextext = true
+ else
+ luamplib.globaltextext = false
+ end
+}}
+% \end{macrocode}
+%
+% The followings are from ConTeXt general, mostly.
+% % We use a dedicated scratchbox.
+% \begin{macrocode}
+\ifx\mplibscratchbox\undefined \newbox\mplibscratchbox \fi
+% \end{macrocode}
+%
+% We encapsulate the litterals.
+% \begin{macrocode}
+\def\mplibstarttoPDF#1#2#3#4{%
+ \hbox\bgroup
+ \xdef\MPllx{#1}\xdef\MPlly{#2}%
+ \xdef\MPurx{#3}\xdef\MPury{#4}%
+ \xdef\MPwidth{\the\dimexpr#3bp-#1bp\relax}%
+ \xdef\MPheight{\the\dimexpr#4bp-#2bp\relax}%
+ \parskip0pt%
+ \leftskip0pt%
+ \parindent0pt%
+ \everypar{}%
+ \setbox\mplibscratchbox\vbox\bgroup
+ \noindent
+}
+\def\mplibstoptoPDF{%
+ \egroup %
+ \setbox\mplibscratchbox\hbox %
+ {\hskip-\MPllx bp%
+ \raise-\MPlly bp%
+ \box\mplibscratchbox}%
+ \setbox\mplibscratchbox\vbox to \MPheight
+ {\vfill
+ \hsize\MPwidth
+ \wd\mplibscratchbox0pt%
+ \ht\mplibscratchbox0pt%
+ \dp\mplibscratchbox0pt%
+ \box\mplibscratchbox}%
+ \wd\mplibscratchbox\MPwidth
+ \ht\mplibscratchbox\MPheight
+ \box\mplibscratchbox
+ \egroup
+}
+% \end{macrocode}
+%
+% Text items have a special handler.
+% \begin{macrocode}
+\def\mplibtextext#1#2#3#4#5{%
+ \begingroup
+ \setbox\mplibscratchbox\hbox
+ {\font\temp=#1 at #2bp%
+ \temp
+ #3}%
+ \setbox\mplibscratchbox\hbox
+ {\hskip#4 bp%
+ \raise#5 bp%
+ \box\mplibscratchbox}%
+ \wd\mplibscratchbox0pt%
+ \ht\mplibscratchbox0pt%
+ \dp\mplibscratchbox0pt%
+ \box\mplibscratchbox
+ \endgroup
+}
+% \end{macrocode}
+%
+% Input |luamplib.cfg| when it exists.
+% \begin{macrocode}
+\openin0=luamplib.cfg
+\ifeof0 \else
+ \closein0
+ \input luamplib.cfg
+\fi
+% \end{macrocode}
+%
+% That's all folks!
+%
+% \iffalse
+%</package>
+% \fi
+%
+% \clearpage
+% \section{The GNU GPL License v2}
+%
+% The GPL requires the complete license text to be distributed along
+% with the code. I recommend the canonical source, instead:
+% \url{http://www.gnu.org/licenses/old-licenses/gpl-2.0.html}.
+% But if you insist on an included copy, here it is.
+% You might want to zoom in.
+%
+% \newsavebox{\gpl}
+% \begin{lrbox}{\gpl}
+% \begin{minipage}{3\textwidth}
+% \columnsep=3\columnsep
+% \begin{multicols}{3}
+% \begin{center}
+% {\Large GNU GENERAL PUBLIC LICENSE\par}
+% \bigskip
+% {Version 2, June 1991}
+% \end{center}
+%
+% \begin{center}
+% {\parindent 0in
+%
+% Copyright \textcopyright\ 1989, 1991 Free Software Foundation, Inc.
+%
+% \bigskip
+%
+% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+%
+% \bigskip
+%
+% Everyone is permitted to copy and distribute verbatim copies
+% of this license document, but changing it is not allowed.
+% }
+% \end{center}
+%
+% \begin{center}
+% {\bf\large Preamble}
+% \end{center}
+%
+%
+% The licenses for most software are designed to take away your freedom to
+% share and change it. By contrast, the GNU General Public License is
+% intended to guarantee your freedom to share and change free software---to
+% make sure the software is free for all its users. This General Public
+% License applies to most of the Free Software Foundation's software and to
+% any other program whose authors commit to using it. (Some other Free
+% Software Foundation software is covered by the GNU Library General Public
+% License instead.) You can apply it to your programs, too.
+%
+% When we speak of free software, we are referring to freedom, not price.
+% Our General Public Licenses are designed to make sure that you have the
+% freedom to distribute copies of free software (and charge for this service
+% if you wish), that you receive source code or can get it if you want it,
+% that you can change the software or use pieces of it in new free programs;
+% and that you know you can do these things.
+%
+% To protect your rights, we need to make restrictions that forbid anyone to
+% deny you these rights or to ask you to surrender the rights. These
+% restrictions translate to certain responsibilities for you if you
+% distribute copies of the software, or if you modify it.
+%
+% For example, if you distribute copies of such a program, whether gratis or
+% for a fee, you must give the recipients all the rights that you have. You
+% must make sure that they, too, receive or can get the source code. And
+% you must show them these terms so they know their rights.
+%
+% We protect your rights with two steps: (1) copyright the software, and (2)
+% offer you this license which gives you legal permission to copy,
+% distribute and/or modify the software.
+%
+% Also, for each author's protection and ours, we want to make certain that
+% everyone understands that there is no warranty for this free software. If
+% the software is modified by someone else and passed on, we want its
+% recipients to know that what they have is not the original, so that any
+% problems introduced by others will not reflect on the original authors'
+% reputations.
+%
+% Finally, any free program is threatened constantly by software patents.
+% We wish to avoid the danger that redistributors of a free program will
+% individually obtain patent licenses, in effect making the program
+% proprietary. To prevent this, we have made it clear that any patent must
+% be licensed for everyone's free use or not licensed at all.
+%
+% The precise terms and conditions for copying, distribution and
+% modification follow.
+%
+% \begin{center}
+% {\Large \sc Terms and Conditions For Copying, Distribution and
+% Modification}
+% \end{center}
+%
+% \begin{enumerate}
+% \item
+% This License applies to any program or other work which contains a notice
+% placed by the copyright holder saying it may be distributed under the
+% terms of this General Public License. The ``Program'', below, refers to
+% any such program or work, and a ``work based on the Program'' means either
+% the Program or any derivative work under copyright law: that is to say, a
+% work containing the Program or a portion of it, either verbatim or with
+% modifications and/or translated into another language. (Hereinafter,
+% translation is included without limitation in the term ``modification''.)
+% Each licensee is addressed as ``you''.
+%
+% Activities other than copying, distribution and modification are not
+% covered by this License; they are outside its scope. The act of
+% running the Program is not restricted, and the output from the Program
+% is covered only if its contents constitute a work based on the
+% Program (independent of having been made by running the Program).
+% Whether that is true depends on what the Program does.
+%
+% \item You may copy and distribute verbatim copies of the Program's source
+% code as you receive it, in any medium, provided that you conspicuously
+% and appropriately publish on each copy an appropriate copyright notice
+% and disclaimer of warranty; keep intact all the notices that refer to
+% this License and to the absence of any warranty; and give any other
+% recipients of the Program a copy of this License along with the Program.
+%
+% You may charge a fee for the physical act of transferring a copy, and you
+% may at your option offer warranty protection in exchange for a fee.
+%
+% \item
+% You may modify your copy or copies of the Program or any portion
+% of it, thus forming a work based on the Program, and copy and
+% distribute such modifications or work under the terms of Section 1
+% above, provided that you also meet all of these conditions:
+%
+% \begin{enumerate}
+%
+% \item
+% You must cause the modified files to carry prominent notices stating that
+% you changed the files and the date of any change.
+%
+% \item
+% You must cause any work that you distribute or publish, that in
+% whole or in part contains or is derived from the Program or any
+% part thereof, to be licensed as a whole at no charge to all third
+% parties under the terms of this License.
+%
+% \item
+% If the modified program normally reads commands interactively
+% when run, you must cause it, when started running for such
+% interactive use in the most ordinary way, to print or display an
+% announcement including an appropriate copyright notice and a
+% notice that there is no warranty (or else, saying that you provide
+% a warranty) and that users may redistribute the program under
+% these conditions, and telling the user how to view a copy of this
+% License. (Exception: if the Program itself is interactive but
+% does not normally print such an announcement, your work based on
+% the Program is not required to print an announcement.)
+%
+% \end{enumerate}
+%
+%
+% These requirements apply to the modified work as a whole. If
+% identifiable sections of that work are not derived from the Program,
+% and can be reasonably considered independent and separate works in
+% themselves, then this License, and its terms, do not apply to those
+% sections when you distribute them as separate works. But when you
+% distribute the same sections as part of a whole which is a work based
+% on the Program, the distribution of the whole must be on the terms of
+% this License, whose permissions for other licensees extend to the
+% entire whole, and thus to each and every part regardless of who wrote it.
+%
+% Thus, it is not the intent of this section to claim rights or contest
+% your rights to work written entirely by you; rather, the intent is to
+% exercise the right to control the distribution of derivative or
+% collective works based on the Program.
+%
+% In addition, mere aggregation of another work not based on the Program
+% with the Program (or with a work based on the Program) on a volume of
+% a storage or distribution medium does not bring the other work under
+% the scope of this License.
+%
+% \item
+% You may copy and distribute the Program (or a work based on it,
+% under Section 2) in object code or executable form under the terms of
+% Sections 1 and 2 above provided that you also do one of the following:
+%
+% \begin{enumerate}
+%
+% \item
+%
+% Accompany it with the complete corresponding machine-readable
+% source code, which must be distributed under the terms of Sections
+% 1 and 2 above on a medium customarily used for software interchange; or,
+%
+% \item
+%
+% Accompany it with a written offer, valid for at least three
+% years, to give any third party, for a charge no more than your
+% cost of physically performing source distribution, a complete
+% machine-readable copy of the corresponding source code, to be
+% distributed under the terms of Sections 1 and 2 above on a medium
+% customarily used for software interchange; or,
+%
+% \item
+%
+% Accompany it with the information you received as to the offer
+% to distribute corresponding source code. (This alternative is
+% allowed only for noncommercial distribution and only if you
+% received the program in object code or executable form with such
+% an offer, in accord with Subsection b above.)
+%
+% \end{enumerate}
+%
+%
+% The source code for a work means the preferred form of the work for
+% making modifications to it. For an executable work, complete source
+% code means all the source code for all modules it contains, plus any
+% associated interface definition files, plus the scripts used to
+% control compilation and installation of the executable. However, as a
+% special exception, the source code distributed need not include
+% anything that is normally distributed (in either source or binary
+% form) with the major components (compiler, kernel, and so on) of the
+% operating system on which the executable runs, unless that component
+% itself accompanies the executable.
+%
+% If distribution of executable or object code is made by offering
+% access to copy from a designated place, then offering equivalent
+% access to copy the source code from the same place counts as
+% distribution of the source code, even though third parties are not
+% compelled to copy the source along with the object code.
+%
+% \item
+% You may not copy, modify, sublicense, or distribute the Program
+% except as expressly provided under this License. Any attempt
+% otherwise to copy, modify, sublicense or distribute the Program is
+% void, and will automatically terminate your rights under this License.
+% However, parties who have received copies, or rights, from you under
+% this License will not have their licenses terminated so long as such
+% parties remain in full compliance.
+%
+% \item
+% You are not required to accept this License, since you have not
+% signed it. However, nothing else grants you permission to modify or
+% distribute the Program or its derivative works. These actions are
+% prohibited by law if you do not accept this License. Therefore, by
+% modifying or distributing the Program (or any work based on the
+% Program), you indicate your acceptance of this License to do so, and
+% all its terms and conditions for copying, distributing or modifying
+% the Program or works based on it.
+%
+% \item
+% Each time you redistribute the Program (or any work based on the
+% Program), the recipient automatically receives a license from the
+% original licensor to copy, distribute or modify the Program subject to
+% these terms and conditions. You may not impose any further
+% restrictions on the recipients' exercise of the rights granted herein.
+% You are not responsible for enforcing compliance by third parties to
+% this License.
+%
+% \item
+% If, as a consequence of a court judgment or allegation of patent
+% infringement or for any other reason (not limited to patent issues),
+% conditions are imposed on you (whether by court order, agreement or
+% otherwise) that contradict the conditions of this License, they do not
+% excuse you from the conditions of this License. If you cannot
+% distribute so as to satisfy simultaneously your obligations under this
+% License and any other pertinent obligations, then as a consequence you
+% may not distribute the Program at all. For example, if a patent
+% license would not permit royalty-free redistribution of the Program by
+% all those who receive copies directly or indirectly through you, then
+% the only way you could satisfy both it and this License would be to
+% refrain entirely from distribution of the Program.
+%
+% If any portion of this section is held invalid or unenforceable under
+% any particular circumstance, the balance of the section is intended to
+% apply and the section as a whole is intended to apply in other
+% circumstances.
+%
+% It is not the purpose of this section to induce you to infringe any
+% patents or other property right claims or to contest validity of any
+% such claims; this section has the sole purpose of protecting the
+% integrity of the free software distribution system, which is
+% implemented by public license practices. Many people have made
+% generous contributions to the wide range of software distributed
+% through that system in reliance on consistent application of that
+% system; it is up to the author/donor to decide if he or she is willing
+% to distribute software through any other system and a licensee cannot
+% impose that choice.
+%
+% This section is intended to make thoroughly clear what is believed to
+% be a consequence of the rest of this License.
+%
+% \item
+% If the distribution and/or use of the Program is restricted in
+% certain countries either by patents or by copyrighted interfaces, the
+% original copyright holder who places the Program under this License
+% may add an explicit geographical distribution limitation excluding
+% those countries, so that distribution is permitted only in or among
+% countries not thus excluded. In such case, this License incorporates
+% the limitation as if written in the body of this License.
+%
+% \item
+% The Free Software Foundation may publish revised and/or new versions
+% of the General Public License from time to time. Such new versions will
+% be similar in spirit to the present version, but may differ in detail to
+% address new problems or concerns.
+%
+% Each version is given a distinguishing version number. If the Program
+% specifies a version number of this License which applies to it and ``any
+% later version'', you have the option of following the terms and conditions
+% either of that version or of any later version published by the Free
+% Software Foundation. If the Program does not specify a version number of
+% this License, you may choose any version ever published by the Free Software
+% Foundation.
+%
+% \item
+% If you wish to incorporate parts of the Program into other free
+% programs whose distribution conditions are different, write to the author
+% to ask for permission. For software which is copyrighted by the Free
+% Software Foundation, write to the Free Software Foundation; we sometimes
+% make exceptions for this. Our decision will be guided by the two goals
+% of preserving the free status of all derivatives of our free software and
+% of promoting the sharing and reuse of software generally.
+%
+% \begin{center}
+% {\Large\sc
+% No Warranty
+% }
+% \end{center}
+%
+% \item
+% {\sc Because the program is licensed free of charge, there is no warranty
+% for the program, to the extent permitted by applicable law. Except when
+% otherwise stated in writing the copyright holders and/or other parties
+% provide the program ``as is'' without warranty of any kind, either expressed
+% or implied, including, but not limited to, the implied warranties of
+% merchantability and fitness for a particular purpose. The entire risk as
+% to the quality and performance of the program is with you. Should the
+% program prove defective, you assume the cost of all necessary servicing,
+% repair or correction.}
+%
+% \item
+% {\sc In no event unless required by applicable law or agreed to in writing
+% will any copyright holder, or any other party who may modify and/or
+% redistribute the program as permitted above, be liable to you for damages,
+% including any general, special, incidental or consequential damages arising
+% out of the use or inability to use the program (including but not limited
+% to loss of data or data being rendered inaccurate or losses sustained by
+% you or third parties or a failure of the program to operate with any other
+% programs), even if such holder or other party has been advised of the
+% possibility of such damages.}
+%
+% \end{enumerate}
+%
+%
+% \begin{center}
+% {\Large\sc End of Terms and Conditions}
+% \end{center}
+%
+%
+% \pagebreak[2]
+%
+% \section*{Appendix: How to Apply These Terms to Your New Programs}
+%
+% If you develop a new program, and you want it to be of the greatest
+% possible use to the public, the best way to achieve this is to make it
+% free software which everyone can redistribute and change under these
+% terms.
+%
+% To do so, attach the following notices to the program. It is safest to
+% attach them to the start of each source file to most effectively convey
+% the exclusion of warranty; and each file should have at least the
+% ``copyright'' line and a pointer to where the full notice is found.
+%
+% \begin{quote}
+% one line to give the program's name and a brief idea of what it does. \\
+% Copyright (C) yyyy name of author \\
+%
+% This program is free software; you can redistribute it and/or modify
+% it under the terms of the GNU General Public License as published by
+% the Free Software Foundation; either version 2 of the License, or
+% (at your option) any later version.
+%
+% This program is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with this program; if not, write to the Free Software
+% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+% \end{quote}
+%
+% Also add information on how to contact you by electronic and paper mail.
+%
+% If the program is interactive, make it output a short notice like this
+% when it starts in an interactive mode:
+%
+% \begin{quote}
+% Gnomovision version 69, Copyright (C) yyyy name of author \\
+% Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. \\
+% This is free software, and you are welcome to redistribute it
+% under certain conditions; type `show c' for details.
+% \end{quote}
+%
+%
+% The hypothetical commands {\tt show w} and {\tt show c} should show the
+% appropriate parts of the General Public License. Of course, the commands
+% you use may be called something other than {\tt show w} and {\tt show c};
+% they could even be mouse-clicks or menu items---whatever suits your
+% program.
+%
+% You should also get your employer (if you work as a programmer) or your
+% school, if any, to sign a ``copyright disclaimer'' for the program, if
+% necessary. Here is a sample; alter the names:
+%
+% \begin{quote}
+% Yoyodyne, Inc., hereby disclaims all copyright interest in the program \\
+% `Gnomovision' (which makes passes at compilers) written by James Hacker. \\
+%
+% signature of Ty Coon, 1 April 1989 \\
+% Ty Coon, President of Vice
+% \end{quote}
+%
+%
+% This General Public License does not permit incorporating your program
+% into proprietary programs. If your program is a subroutine library, you
+% may consider it more useful to permit linking proprietary applications
+% with the library. If this is what you want to do, use the GNU Library
+% General Public License instead of this License.
+%
+% \end{multicols}
+% \end{minipage}
+% \end{lrbox}
+%
+% \begin{center}
+% \scalebox{0.33}{\usebox{\gpl}}
+% \end{center}
+%
+% \Finale
+\endinput
diff --git a/macros/luatex/generic/luamplib/luamplib.pdf b/macros/luatex/generic/luamplib/luamplib.pdf
new file mode 100644
index 0000000000..96852e5d3f
--- /dev/null
+++ b/macros/luatex/generic/luamplib/luamplib.pdf
Binary files differ
diff --git a/macros/luatex/generic/luamplib/test-luamplib-latex.tex b/macros/luatex/generic/luamplib/test-luamplib-latex.tex
new file mode 100644
index 0000000000..237a289748
--- /dev/null
+++ b/macros/luatex/generic/luamplib/test-luamplib-latex.tex
@@ -0,0 +1,164 @@
+\documentclass{article}
+\usepackage{luamplib}
+\usepackage{xcolor}
+\everymplib{ beginfig(0); }
+\everyendmplib{ endfig; }
+\mpliblegacybehavior{true}%
+\begin{document}
+\tracingcommands1
+A%
+\begin{mplibcode}
+%% test all printable ascii chars in comments
+%% ( 2 < F P Z d n x
+%% ) 3 = G Q [ e o y
+%% * 4 > H R \ f p z
+%% ! + 5 ? I S ] g q {
+%% " , 6 @ J T ^ h r |
+%% # - 7 A K U _ i s }
+%% $ . 8 B L V ` j t ~
+%% % / 9 C M W a k u DEL
+%% & 0 : D N X b l v
+%% ´ 1 ; E O Y c m w
+ fill fullcircle scaled 20; %% actual <tab> to make sure it works
+\end{mplibcode}%
+B\par
+\everymplib{}\everyendmplib{}% reset toks
+A%
+\begin{mplibcode}
+verbatimtex \lower.2em etex
+beginfig(0);
+draw origin--(1cm,0) withcolor \mpcolor{teal};
+draw btex g etex withcolor \mpcolor{orange};
+draw btex\tracingcommands0
+ multi%
+ \begin{huge}line\end{huge}%
+ texcode
+ with \%
+ etex shifted (10,0);
+draw bbox currentpicture;
+endfig;
+
+beginfig(18);
+numeric u;
+u = 1cm;
+draw (0,2u)--(0,0)--(4u,0);
+pickup pencircle scaled 1pt;
+draw (0,0){up}
+ for i=1 upto 8: ..(i/2,sqrt(i/2))*u endfor;
+label.lrt(btex $\sqrt x$ etex, (3,sqrt 3)*u);
+label.bot(btex $x$ etex, (2u,0));
+label.lft(btex $y$ etex, (0,u));
+endfig;
+\end{mplibcode}%
+B\par
+A%
+\begin{mplibcode}
+beginfig(2);
+numeric u; u=1cm;
+z1=-z2=(-u,0);
+for i = 1 upto 3:
+ draw z1..(0, i*u)..z2;
+ label.top(TEX("$e_{" & decimal(i) & "}$"), (0, i*u))
+ withcolor \mpcolor{red!70!blue};
+endfor;
+endfig;
+\end{mplibcode}%
+B\par\leavevmode
+\mplibcodeinherit{enable}%
+\mplibglobaltextext{enable}%
+\everymplib{ beginfig(0);}\everyendmplib{ endfig;}%
+\begin{mplibcode}
+ label(btex $\sqrt{2}$ etex, origin);
+ draw fullcircle scaled 20;
+ picture pic; pic := currentpicture;
+\end{mplibcode}%
+\begin{mplibcode}
+ currentpicture := pic scaled 2;
+\end{mplibcode}%
+\everymplib{}\everyendmplib{}%
+\mplibcodeinherit{disable}%
+\mplibglobaltextext{disable}\par
+\mplibsetformat{metafun}%
+\begin{mplibcode}
+verbatimtex \moveright 0.4\hsize etex
+beginfig(0);
+path p; p:= fullcircle scaled 2cm yshifted .5cm;
+fill p withcolor transparent("normal", 0.5, red);
+fill p rotated 120 withcolor transparent("normal", 0.5, green);
+fill p rotated 240 withcolor transparent("normal", 0.5, blue);
+endfig;
+verbatimtex \leavevmode etex
+picture p; p := btex MetaPost etex scaled 2;
+beginfig(1);
+linear_shade(bbox p,0,blue,.7white);
+draw p withcolor white;
+endfig;
+verbatimtex \kern10pt etex
+beginfig(2);
+circular_shade(bbox p,0,blue,.7white);
+draw p withcolor white;
+endfig;
+\end{mplibcode}%
+
+\newbox\mympbox
+\begin{mplibcode}
+verbatimtex \global\setbox\mympbox etex
+beginfig(0);
+breadth=.667\mpdim\linewidth;
+height=2pt;
+x1=0; x2=x6=.333x4; x5=x3=.667x4;
+x4=breadth;
+y1=y4=height/2; y2=y3=height; y5=y6=0;
+fill z1--z2--z3--z4--z5--z6--cycle;
+endfig;
+\end{mplibcode}%
+\copy\mympbox
+\copy\mympbox
+\copy\mympbox
+\copy\mympbox
+
+\mplibnumbersystem{double}%
+\begin{mplibcode}
+beginfig(0);
+u := 10**5*(10**-4);
+draw unitsquare scaled u;
+endfig;
+\end{mplibcode}%
+\mplibsetformat{plain}%
+\begin{mplibcode}
+ input graph;
+ beginfig(0);
+ draw begingraph(100,100);
+ gdraw (10,10)--(30,35)--(50,25)--(70,80)--(90,90);
+ autogrid(otick.bot,);
+ for y=20,40,60,80:
+ grid.lft(format("%e",1000y), y) withcolor .85white;
+ endfor
+ endgraph;
+ endfig;
+\end{mplibcode}%
+\mplibtextextlabel{enable}%
+\begin{mplibcode}
+beginfig(0);
+dotlabel.rt("$\sqrt2$",origin);
+endfig;
+\end{mplibcode}%
+\leavevmode
+\begin{mplibcode}
+ D := sqrt(2)**7;
+ beginfig(0);
+ draw fullcircle scaled D;
+ VerbatimTeX("\gdef\Dia{" & decimal D & "}");
+ endfig;
+\end{mplibcode}%
+diameter:\Dia bp.%
+\begin{mplibcode}
+ vardef rotatedlabel@#(expr str, loc, angl) =
+ draw thelabel@#(str, loc) rotatedaround(loc, angl)
+ enddef;
+
+ beginfig(1);
+ rotatedlabel.top(textext("Rotated!"), origin, 45);
+ endfig;
+\end{mplibcode}%
+\end{document}
diff --git a/macros/luatex/generic/luamplib/test-luamplib-plain.tex b/macros/luatex/generic/luamplib/test-luamplib-plain.tex
new file mode 100644
index 0000000000..2161cf2f76
--- /dev/null
+++ b/macros/luatex/generic/luamplib/test-luamplib-plain.tex
@@ -0,0 +1,162 @@
+\input miniltx
+\input color
+\definecolor{orange}{rgb}{1,0.5,0}
+\input luamplib.sty
+\mpliblegacybehavior{true}%
+\everymplib{ beginfig(0); }\everyendmplib{ endfig; }
+\tracingcommands1
+A%
+\mplibcode
+%% test all printable ascii chars in comments
+%% ( 2 < F P Z d n x
+%% ) 3 = G Q [ e o y
+%% * 4 > H R \ f p z
+%% ! + 5 ? I S ] g q {
+%% " , 6 @ J T ^ h r |
+%% # - 7 A K U _ i s }
+%% $ . 8 B L V ` j t ~
+%% % / 9 C M W a k u DEL
+%% & 0 : D N X b l v
+%% ´ 1 ; E O Y c m w
+ fill fullcircle scaled 20;
+\endmplibcode
+B\par
+\everymplib{}\everyendmplib{}% reset toks
+A%
+\mplibcode
+verbatimtex \lower.2em etex
+beginfig(0);
+draw origin--(1cm,0) withcolor red;
+draw btex g etex withcolor blue;
+draw btex\tracingcommands0 multi
+ line
+ tex code
+ 100 \% color
+ etex shifted (20,0);
+draw textext("\tracingcommands0 textext 50\% color") shifted (10,-10) withcolor .5white;
+draw bbox currentpicture;
+endfig;
+
+beginfig(18);
+numeric u;
+u = 1cm;
+draw (0,2u)--(0,0)--(4u,0);
+pickup pencircle scaled 1pt;
+draw (0,0){up}
+ for i=1 upto 8: ..(i/2,sqrt(i/2))*u endfor;
+label.lrt(btex $\sqrt x$ etex, (3,sqrt 3)*u);
+label.bot(btex $x$ etex, (2u,0));
+label.lft(btex $y$ etex, (0,u));
+endfig;
+\endmplibcode
+B\par
+A%
+\mplibcode
+beginfig(2);
+numeric u; u=1cm;
+z1=-z2=(-u,0);
+for i = 1 upto 3:
+ draw z1..(0, i*u)..z2;
+ label.top(TEX("$e_{" & decimal(i) & "}$"), (0, i*u)) withcolor \mpcolor{orange};
+endfor;
+endfig;
+\endmplibcode
+B\par\leavevmode
+\mplibcodeinherit{enable}%
+\mplibglobaltextext{enable}%
+\everymplib{ beginfig(0);}\everyendmplib{ endfig;}%
+\mplibcode
+ label(btex $\sqrt{2}$ etex, origin);
+ draw fullcircle scaled 20;
+ picture pic; pic := currentpicture;
+\endmplibcode
+\mplibcode
+ currentpicture := pic scaled 2;
+\endmplibcode
+\everymplib{}\everyendmplib{}%
+\mplibcodeinherit{disable}%
+\mplibglobaltextext{disable}\par
+\mplibsetformat{metafun}%
+\mplibcode
+verbatimtex \moveright 0.4\hsize etex
+beginfig(0);
+path p; p:= fullcircle scaled 2cm yshifted .5cm;
+fill p withcolor transparent("normal", 0.5, red);
+fill p rotated 120 withcolor transparent("normal", 0.5, green);
+fill p rotated 240 withcolor transparent("normal", 0.5, blue);
+endfig;
+verbatimtex \leavevmode etex
+picture p; p := btex MetaPost etex scaled 2;
+beginfig(1);
+linear_shade(bbox p,0,blue,.7white);
+draw p withcolor white;
+endfig;
+verbatimtex \kern10pt etex
+beginfig(2);
+circular_shade(bbox p,0,blue,.7white);
+draw p withcolor white;
+endfig;
+\endmplibcode
+
+\newbox\mympbox
+\mplibcode
+verbatimtex \global\setbox\mympbox etex
+beginfig(0);
+breadth=.667\mpdim\hsize;
+height=2pt;
+x1=0; x2=x6=.333x4; x5=x3=.667x4;
+x4=breadth;
+y1=y4=height/2; y2=y3=height; y5=y6=0;
+fill z1--z2--z3--z4--z5--z6--cycle;
+endfig;
+\endmplibcode
+\copy\mympbox
+\copy\mympbox
+\copy\mympbox
+\copy\mympbox
+
+\mplibnumbersystem{double}%
+\mplibcode
+beginfig(0);
+u := 10**5*(10**-4);
+draw unitsquare scaled u;
+endfig;
+\endmplibcode
+\mplibsetformat{plain}%
+\mplibcode
+ input graph;
+ beginfig(0);
+ draw begingraph(100,100);
+ gdraw (10,10)--(30,35)--(50,25)--(70,80)--(90,90);
+ autogrid(otick.bot,);
+ for y=20,40,60,80:
+ grid.lft(format("%e",1000y), y) withcolor .85white;
+ endfor
+ endgraph;
+ endfig;
+\endmplibcode
+\mplibtextextlabel{enable}%
+\mplibcode
+beginfig(0);
+dotlabel.rt("$\sqrt2$",origin);
+endfig;
+\endmplibcode
+\leavevmode
+\mplibcode
+ D := sqrt(2)**7;
+ beginfig(0);
+ draw fullcircle scaled D;
+ VerbatimTeX("\gdef\Dia{" & decimal D & "}");
+ endfig;
+\endmplibcode
+diameter:\Dia bp.%
+\mplibcode
+ vardef rotatedlabel@#(expr str, loc, angl) =
+ draw thelabel@#(str, loc) rotatedaround(loc, angl)
+ enddef;
+
+ beginfig(1);
+ rotatedlabel.top(textext("Rotated!"), origin, 45);
+ endfig;
+\endmplibcode
+\bye