summaryrefslogtreecommitdiff
path: root/Master
diff options
context:
space:
mode:
Diffstat (limited to 'Master')
-rw-r--r--Master/texmf-dist/doc/luatex/luamplib/NEWS13
-rw-r--r--Master/texmf-dist/doc/luatex/luamplib/luamplib.pdfbin154238 -> 163569 bytes
-rw-r--r--Master/texmf-dist/doc/luatex/luamplib/test-luamplib-latex.tex1
-rw-r--r--Master/texmf-dist/doc/luatex/luamplib/test-luamplib-plain.tex1
-rw-r--r--Master/texmf-dist/source/luatex/luamplib/luamplib.dtx1478
-rw-r--r--Master/texmf-dist/tex/luatex/luamplib/luamplib.lua887
-rw-r--r--Master/texmf-dist/tex/luatex/luamplib/luamplib.sty123
7 files changed, 1331 insertions, 1172 deletions
diff --git a/Master/texmf-dist/doc/luatex/luamplib/NEWS b/Master/texmf-dist/doc/luatex/luamplib/NEWS
index 7eaf2ba8636..8fb7136dba6 100644
--- a/Master/texmf-dist/doc/luatex/luamplib/NEWS
+++ b/Master/texmf-dist/doc/luatex/luamplib/NEWS
@@ -1,5 +1,18 @@
History of the luamplib package
+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)
diff --git a/Master/texmf-dist/doc/luatex/luamplib/luamplib.pdf b/Master/texmf-dist/doc/luatex/luamplib/luamplib.pdf
index 8cff394e46a..e119f2d6605 100644
--- a/Master/texmf-dist/doc/luatex/luamplib/luamplib.pdf
+++ b/Master/texmf-dist/doc/luatex/luamplib/luamplib.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/luatex/luamplib/test-luamplib-latex.tex b/Master/texmf-dist/doc/luatex/luamplib/test-luamplib-latex.tex
index a500e2181dd..237a2897480 100644
--- a/Master/texmf-dist/doc/luatex/luamplib/test-luamplib-latex.tex
+++ b/Master/texmf-dist/doc/luatex/luamplib/test-luamplib-latex.tex
@@ -3,6 +3,7 @@
\usepackage{xcolor}
\everymplib{ beginfig(0); }
\everyendmplib{ endfig; }
+\mpliblegacybehavior{true}%
\begin{document}
\tracingcommands1
A%
diff --git a/Master/texmf-dist/doc/luatex/luamplib/test-luamplib-plain.tex b/Master/texmf-dist/doc/luatex/luamplib/test-luamplib-plain.tex
index d7a8ed90bcc..2161cf2f766 100644
--- a/Master/texmf-dist/doc/luatex/luamplib/test-luamplib-plain.tex
+++ b/Master/texmf-dist/doc/luatex/luamplib/test-luamplib-plain.tex
@@ -2,6 +2,7 @@
\input color
\definecolor{orange}{rgb}{1,0.5,0}
\input luamplib.sty
+\mpliblegacybehavior{true}%
\everymplib{ beginfig(0); }\everyendmplib{ endfig; }
\tracingcommands1
A%
diff --git a/Master/texmf-dist/source/luatex/luamplib/luamplib.dtx b/Master/texmf-dist/source/luatex/luamplib/luamplib.dtx
index 1de69bafd8e..35ac43b3c02 100644
--- a/Master/texmf-dist/source/luatex/luamplib/luamplib.dtx
+++ b/Master/texmf-dist/source/luatex/luamplib/luamplib.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment -- by the way, this file contains UTF-8
%
-% Copyright (C) 2008-2018 by Hans Hagen, Taco Hoekwater, Elie Roux,
+% 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>
@@ -85,7 +85,7 @@ See source file '\inFileName' for licencing and contact information.
%<*driver>
\NeedsTeXFormat{LaTeX2e}
\ProvidesFile{luamplib.drv}%
- [2018/09/27 v2.12.5 Interface for using the mplib library]%
+ [2019/03/20 v2.20.0 Interface for using the mplib library]%
\documentclass{ltxdoc}
\usepackage{metalogo,multicol,mdwlist,fancyvrb,xspace}
\usepackage[x11names]{xcolor}
@@ -153,18 +153,18 @@ See source file '\inFileName' for licencing and contact information.
% \author{Hans Hagen, Taco Hoekwater, Elie Roux, Philipp Gesang and Kim Dohyun\\
% Maintainer: LuaLaTeX Maintainers ---
% Support: \email{lualatex-dev@tug.org}}
-% \date{2018/09/27 v2.12.5}
+% \date{2019/03/20 v2.20.0}
%
% \maketitle
%
% \begin{abstract}
-% Package to have metapost code typeset directly in a document with Lua\TeX .
+% 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
+% 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.
@@ -194,15 +194,29 @@ See source file '\inFileName' for licencing and contact information.
% |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}. However,
-% |verbatimtex ... etex| will be entirely ignored in this case.
-% \item |verbatimtex ... etex| (in \TeX\ file) that comes just before |beginfig()|
-% is not ignored, but the \TeX\ code inbetween will be inserted before the
+% 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 cuations 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).
-% \textsc{e.g.}
% \begin{verbatim}
% \mplibcode
% verbatimtex \moveright 3cm etex; beginfig(0); ... endfig;
@@ -213,11 +227,10 @@ See source file '\inFileName' for licencing and contact information.
% \end{verbatim}
% \textsc{n.b.} \cs{endgraf} should be used instead of \cs{par} inside
% |verbatimtex ... etex|.
-% \item
-% \TeX\ code in |VerbatimTeX(...)| or |verbatimtex ... etex| (in \TeX\ file)
+%
+% By contrast, \TeX\ code in |VerbatimTeX(...)| or |verbatimtex ... etex|
% between |beginfig()| and |endfig| will be inserted
% after flushing out the mplib figure.
-% \textsc{e.g.}
% \begin{verbatim}
% \mplibcode
% D := sqrt(2)**7;
@@ -228,32 +241,48 @@ See source file '\inFileName' for licencing and contact information.
% \endmplibcode
% diameter: \Dia bp.
% \end{verbatim}
-% \item Notice that, after each figure is processed, macro \cs{MPwidth} stores
+%
+% \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|.
-% \item Since v2.3, new macros \cs{everymplib} and \cs{everyendmplib} redefine
+%
+% \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.
-% \textsc{e.g.}
% \begin{verbatim}
-% \everymplib{ verbatimtex \leavevmode etex; beginfig(0); }
+% \everymplib{ beginfig(0); }
% \everyendmplib{ endfig; }
-% \mplibcode % beginfig/endfig not needed; always in horizontal mode
+% \mplibcode % beginfig/endfig not needed
% draw fullcircle scaled 1cm;
% \endmplibcode
% \end{verbatim}
-% \textsc{n.b.} Many users have complained that mplib figures do not
-% respect alignment commands such as \cs{centering} or \cs{raggedleft}.
-% That's because \textsf{luamplib} does not force horizontal or vertical mode.
-% If you want all mplib figures center- (or right-) aligned, please use
-% \cs{everymplib} command with \cs{leavevmode} as shown above.
-% \item Since v2.3, \cs{mpdim} and other raw \TeX\ commands are allowed
+%
+% \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.
-% \textsc{e.g.}
% \begin{verbatim}
% \begin{mplibcode}
% draw origin--(\mpdim{\linewidth},0) withpen pencircle scaled 4
@@ -264,17 +293,24 @@ See source file '\inFileName' for licencing and contact information.
% |btex ... etex| as provided by gmp package. As \textsf{luamplib}
% automatically protects \TeX\ code inbetween, \cs{btex} is not supported
% here.
-% \item With \cs{mpcolor} command, color names or expressions of
+%
+% \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.
-% \item Users can choose |numbersystem| option since v2.4.
-% The default value |scaled| can be changed to |double| by declaring
-% |\mplibnumbersystem{double}|. For details see
+%
+% \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}.
-% \item To support |btex ... etex| in external |.mp| files, \textsf{luamplib}
+%
+% \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
@@ -288,14 +324,17 @@ See source file '\inFileName' for licencing and contact information.
% 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.
-% \item 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
+%
+% 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.
-% \item Starting with v2.6, |\mplibtextextlabel{enable}| enables
+%
+% \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,
@@ -304,13 +343,15 @@ See source file '\inFileName' for licencing and contact information.
% 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.
-% \item Starting with v2.9, |\mplibcodeinherit{enable}| enables the inheritance
+%
+% \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.
%
-% \textsc{n.b.}
+% \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
@@ -331,17 +372,22 @@ See source file '\inFileName' for licencing and contact information.
% currentpicture := pic scaled 2;
% \endmplibcode
% \end{verbatim}
-% \item Starting with v2.11, users can issue |\mplibverbatim{enable}|, after which
+%
+% \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,
-% users cannot use |\mpdim|, |\mpcolor| etc. All \TeX\ commands outside of
+% users cannot use |\mpdim|, but |\mpcolor| is OK.
+% All other \TeX\ commands outside
% |btex ... etex| or |verbatimtex ... etex| are not expanded and will be fed
% literally into the mplib process.
-% \item At the end of package loading, \textsf{luamplib} searches
+%
+% \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{mplibcachedir}
+% Frequently used settings such as \cs{everymplib} or \cs{mplibforcehmode}
% are suitable for going into this file.
%
-% \end{itemize}
+% \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
@@ -355,46 +401,38 @@ See source file '\inFileName' for licencing and contact information.
% \iffalse
%<*lua>
% \fi
-% Use the |luamplib| namespace, since |mplib| is for the metapost library
-% itself. \ConTeXt{} uses |metapost|.
%
% \begin{macrocode}
-luamplib = luamplib or { }
+luatexbase.provides_module {
+ name = "luamplib",
+ version = "2.20.0",
+ date = "2019/03/20",
+ 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}
-% Identification.
%
+% 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 = ""
-luatexbase.provides_module {
- name = "luamplib",
- version = "2.12.5",
- date = "2018/09/27",
- description = "Lua package to typeset Metapost with LuaTeX's MPLib.",
-}
-
% \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 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
-
-local stringgsub = string.gsub
-local stringfind = string.find
-local stringmatch = string.match
-local stringgmatch = string.gmatch
-local stringexplode = string.explode
local tableconcat = table.concat
local texsprint = tex.sprint
local textprint = tex.tprint
@@ -402,6 +440,12 @@ local textprint = tex.tprint
local texget = tex.get
local texgettoks = tex.gettoks
local texgetbox = tex.getbox
+local texruntoks = tex.runtoks
+local texscantoks = tex.scantoks
+
+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')
@@ -413,25 +457,19 @@ local lfsmkdir = lfs.mkdir
local lfstouch = lfs.touch
local ioopen = io.open
-local file = file or { }
% \end{macrocode}
-% This is a small trick for \LaTeX . In \LaTeX\ we read the metapost code
-% line by line, but it needs to be passed entirely to |process()|, so we
-% simply add the lines in |data| and at the end we call |process(data)|.
-%
-% A few helpers, taken from |l-file.lua|.
%
+% 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 (stringgsub(filename,"%.[%a%d]+$","")) .. "." .. suffix
+ return (filename:gsub("%.[%a%d]+$","")) .. "." .. suffix
end
local stripsuffix = file.stripsuffix or function(filename)
- return (stringgsub(filename,"%.[%a%d]+$",""))
+ return (filename:gsub("%.[%a%d]+$",""))
end
-% \end{macrocode}
-% |btex ... etex| in input .mp files will be replaced in finder.
-% \begin{macrocode}
local is_writable = file.is_writable or function(name)
if lfsisdir(name) then
name = name .. "/_luam_plib_temp_file_"
@@ -444,12 +482,18 @@ local is_writable = file.is_writable or function(name)
end
local mk_full_path = lfs.mkdirs or function(path)
local full = ""
- for sub in stringgmatch(path,"(/*[^\\/]+)") do
+ 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")
@@ -459,7 +503,7 @@ local outputdir
if lfstouch then
local texmfvar = kpse.expand_var('$TEXMFVAR')
if texmfvar and texmfvar ~= "" and texmfvar ~= '$TEXMFVAR' then
- for _,dir in next,stringexplode(texmfvar,os.type == "windows" and ";" or ":") do
+ for _,dir in next, texmfvar:explode(os.type == "windows" and ";" or ":") do
if not lfsisdir(dir) then
mk_full_path(dir)
end
@@ -475,7 +519,7 @@ end
if not outputdir then
outputdir = "."
for _,v in ipairs(arg) do
- local t = stringmatch(v,"%-output%-directory=(.+)")
+ local t = v:match("%-output%-directory=(.+)")
if t then
outputdir = t
break
@@ -500,48 +544,32 @@ function luamplib.getcachedir(dir)
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-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,
+ ["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
@@ -560,25 +588,15 @@ local function replaceformatmp(file,newfile,ofmodify)
return newfile
end
-local esctex = "!!!T!!!E!!!X!!!"
-local esclbr = "!!!!!LEFTBRCE!!!!!"
-local escrbr = "!!!!!RGHTBRCE!!!!!"
-local escpcnt = "!!!!!PERCENT!!!!!"
-local eschash = "!!!!!HASH!!!!!"
-local begname = "%f[A-Z_a-z]"
-local endname = "%f[^A-Z_a-z]"
-
-local btex_etex = begname.."btex"..endname.."%s*(.-)%s*"..begname.."etex"..endname
-local verbatimtex_etex = begname.."verbatimtex"..endname.."%s*(.-)%s*"..begname.."etex"..endname
-
-local function protecttexcontents(str)
- return str:gsub("\\%%", "\\"..escpcnt)
- :gsub("%%.-\n", "")
- :gsub("%%.-$", "")
- :gsub('"', '"&ditto&"')
- :gsub("\n%s*", " ")
- :gsub(escpcnt, "%%")
-end
+% \end{macrocode}
+%
+% Replace |btex ... etex| and |verbatimtex ... etex| in input files,
+% if needed.
+% \begin{macrocode}
+local name_b = "%f[A-Z_a-z]"
+local name_e = "%f[^A-Z_a-z]"
+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")
@@ -588,33 +606,29 @@ local function replaceinputmpfile (name,file)
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
+ 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 = data:gsub("\"[^\n]-\"", function(str)
- return str:gsub("([bem])tex"..endname,"%1"..esctex)
- end)
-
- data, cnt = data:gsub(btex_etex, function(str)
- return format("rawtextext(\"%s\")",protecttexcontents(str))
- end)
+ data, cnt = data:gsub(btex_etex, "btex %1 etex ") -- space
count = count + cnt
- data, cnt = data:gsub(verbatimtex_etex, "")
+ data, cnt = data:gsub(verbatimtex_etex, "verbatimtex %1 etex;") -- semicolon
count = count + cnt
- data = data:gsub("\"[^\n]-\"", function(str) -- restore string btex .. etex
- return str:gsub("([bem])"..esctex, "%1tex")
- end)
-
if count == 0 then
noneedtoreplace[name] = true
fh = ioopen(newfile,"w");
@@ -624,6 +638,7 @@ local function replaceinputmpfile (name,file)
end
return file
end
+
fh = ioopen(newfile,"w")
if not fh then return file end
fh:write(data); fh:close()
@@ -631,14 +646,12 @@ local function replaceinputmpfile (name,file)
return newfile
end
-local randomseed = nil
% \end{macrocode}
-% As the finder function for |mplib|, use the |kpse| library and
-% make it behave like as if MetaPost was used (or almost, since the engine
-% name is not set this way---not sure if this is a problem).
%
+% 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 = {
@@ -658,156 +671,126 @@ local function finder(name, mode, ftype)
end
return replaceinputmpfile(name,file)
end
- return mpkpse:find_file(name,stringmatch(name,"[a-zA-Z]+$"))
+ return mpkpse:find_file(name, name:match("[a-zA-Z]+$"))
end
end
luamplib.finder = finder
% \end{macrocode}
-% The rest of this module is not documented. More info can be found in the
-% \LuaTeX{} manual, articles in user group journals and the files that
-% ship with \ConTeXt.
%
+% 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}
-
-function luamplib.resetlastlog()
- luamplib.lastlog = ""
+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
-% \end{macrocode}
-% Below included is section that defines fallbacks for older
-% versions of mplib.
-%
-% \begin{macrocode}
-local mplibone = tonumber(mplib.version()) <= 1.50
-
-if mplibone then
+local preamble = [[
+ boolean mplib ; mplib := true ;
+ let dump = endinput ;
+ let normalfontsize = fontsize;
+ input %s ;
+]]
- luamplib.make = luamplib.make or function(name,mem_name,dump)
- local t = os.clock()
- local mpx = mplib.new {
- ini_version = true,
- find_file = luamplib.finder,
- job_name = stripsuffix(name)
- }
- mpx:execute(format("input %s ;",name))
- if dump then
- mpx:execute("dump ;")
- info("format %s made and dumped for %s in %0.3f seconds",mem_name,name,os.clock()-t)
- else
- info("%s read in %0.3f seconds",name,os.clock()-t)
- end
- return mpx
- end
+local function luamplibresetlastlog()
+ luamplib.lastlog = ""
+end
- function luamplib.load(name)
- local mem_name = replacesuffix(name,"mem")
- local mpx = mplib.new {
- ini_version = false,
- mem_name = mem_name,
- find_file = luamplib.finder
- }
- if not mpx and type(luamplib.make) == "function" then
- -- when i have time i'll locate the format and dump
- mpx = luamplib.make(name,mem_name)
- end
- if mpx then
- info("using format %s",mem_name,false)
- return mpx, nil
- else
- return nil, { status = 99, error = "out of memory or invalid format" }
+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
-else
-
+local function luamplibload (name)
+ local mpx = mplib.new {
+ ini_version = true,
+ find_file = luamplib.finder,
% \end{macrocode}
-% These are the versions called with sufficiently recent mplib.
%
-% \begin{macrocode}
- local preamble = [[
- boolean mplib ; mplib := true ;
- let dump = endinput ;
- let normalfontsize = fontsize;
- input %s ;
- ]]
-
- luamplib.make = luamplib.make or function()
- end
-
- function luamplib.load(name,verbatim)
- local mpx = mplib.new {
- ini_version = true,
- find_file = luamplib.finder,
-% \end{macrocode}
-% Provides |numbersystem| option since v2.4. Default value |"scaled"|
-% can be changed by declaring |\mplibnumbersystem{double}|.
+% 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}
- math_mode = luamplib.numbersystem,
- random_seed = randomseed,
- }
+ make_text = luamplib.maketext,
+ run_script = luamplib.runscript,
+ math_mode = luamplib.numbersystem,
+ extensions = 1,
+ }
% \end{macrocode}
-% Append our own preamble to the preamble above.
+%
+% Append our own MetaPost preamble to the preamble above.
% \begin{macrocode}
- local preamble = preamble .. (verbatim and "" or luamplib.mplibcodepreamble)
- if luamplib.textextlabel then
- preamble = preamble .. (verbatim and "" or 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
- luamplib.reporterror(result)
- return mpx, result
+ 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) --- used in .sty
+local function setformat (name)
currentformat = name
end
luamplib.setformat = setformat
-
-luamplib.reporterror = function (result)
- if not result then
- err("no result object returned")
- else
- local t, e, l = result.term, result.error, result.log
- local log = stringgsub(t or l or "no-term","^%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 process_indeed (mpx, data, indeed)
+% \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 = luamplib.reporterror(result)
- if indeed and log then
+ local log = reporterror(result)
+ if log then
if luamplib.showlog then
info("%s",luamplib.lastlog)
- luamplib.resetlastlog()
+ 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,
+% it does not raise error but just prints a warning,
% even if output has no figure.
% \begin{macrocode}
- if stringfind(log,"\n>>") then info("%s",log) end
+ if log:find("\n>>") then info("%s",log) end
converted = luamplib.convert(result)
else
info("%s",log)
@@ -821,211 +804,279 @@ local function process_indeed (mpx, data, indeed)
end
% \end{macrocode}
-% v2.9 has introduced the concept of `code inherit'
+%
+% v2.9 has introduced the concept of ``code inherit''
% \begin{macrocode}
luamplib.codeinherit = false
local mplibinstances = {}
-local process = function (data,indeed,verbatim)
+
+local function process (data)
% \end{macrocode}
-% workaround issue \#70
+%
+% Workaround issue \#70
% \begin{macrocode}
- if not stringfind(data, begname.."beginfig%s*%([%+%-%s]*%d[%.%d%s]*%)") then
+ if not data:find(name_b.."beginfig%s*%([%+%-%s]*%d[%.%d%s]*%)") then
data = data .. "beginfig(-1);endfig;"
end
- local standalone, firstpass = not luamplib.codeinherit, not indeed
+ local standalone = not luamplib.codeinherit
local currfmt = currentformat .. (luamplib.numbersystem or "scaled")
- currfmt = firstpass and currfmt or (currfmt.."2")
+ .. 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
- randomseed = firstpass and math.random(65535) or randomseed
- mpx = luamplib.load(currentformat,verbatim)
+ mpx = luamplibload(currentformat)
mplibinstances[currfmt] = mpx
end
- return process_indeed(mpx, data, indeed)
+ return process_indeed(mpx, data)
end
-luamplib.process = process
-local function getobjects(result,figure,f)
- return figure:objects()
+% \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{macrocode}
+local function run_tex_code_no_use (str, cat)
+ cat = cat or catlatex
+ texscantoks("mplibtmptoks", cat, str)
+ texruntoks("mplibtmptoks")
end
-local function convert(result, flusher)
- luamplib.flush(result, flusher)
- return true -- done
+local function run_tex_code (str, cat)
+ cat = cat or catlatex
+ texruntoks(function() texsprint(cat, str) end)
end
-luamplib.convert = convert
-local function pdf_startfigure(n,llx,lly,urx,ury)
% \end{macrocode}
-% The following line has been slightly modified by Kim.
+%
+% 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}
- texsprint(format("\\mplibstarttoPDF{%f}{%f}{%f}{%f}",llx,lly,urx,ury))
-end
+local tex_box_id = 2047
+% \end{macrocode}
+%
+% For conversion of |sp| to |bp|.
+% \begin{macrocode}
+local factor = 65536*(7227/7200)
-local function pdf_stopfigure()
- texsprint("\\mplibstoptoPDF")
+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}
-% |tex.tprint| and catcode regime -2, as sometimes |#| gets doubled
-% in the argument of pdfliteral. --- modified by Kim
+%
+% Make |color| or |xcolor|'s color expressions usable,
+% with \cs{mpcolor} or |mplibcolor|
% \begin{macrocode}
-local function pdf_literalcode(fmt,...) -- table
- textprint({"\\mplibtoPDF{"},{-2,format(fmt,...)},{"}"})
+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
-luamplib.pdf_literalcode = pdf_literalcode
-local function pdf_textfigure(font,size,text,width,height,depth)
% \end{macrocode}
-% The following three lines have been modified by Kim.
+%
+% \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}
- -- if text == "" then text = "\0" end -- char(0) has gone
- 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))
+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
-luamplib.pdf_textfigure = pdf_textfigure
-local bend_tolerance = 131/65536
+% \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
-local rx, sx, sy, ry, tx, ty, divider = 1, 0, 0, 1, 0, 0, 1
+% \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 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
+local function legacy_mplibcode_reset ()
+ tex_code_pre_mplib = {}
+ luamplib.figid = 1
end
-local function concat(px, py) -- no tx, ty here
- return (sy*px-ry*py)/divider,(sx*py-rx*px)/divider
+local function process_verbatimtex_prefig (str)
+ if str then
+ tex_code_pre_mplib[luamplib.figid] = str
+ end
+ return ""
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
+local function process_verbatimtex_infig (str)
+ if str then
+ return format("special \"postmplibverbtex=%s\";", str)
end
- return true
+ return ""
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)
+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}
+%
+% As of 2019-03, |metafun| format is not usable (issue \#79).
+% This might workarounds the problem.
+% \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
+LUATEXFUNCTIONALITY = LUATEXFUNCTIONALITY or 0
+
+% \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] = "(" .. concat(value,",") .. ")"
+ else -- boolean or whatever
+ buffer[#buffer+1] = tostring(value)
+ end
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))
+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
- 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))
+ local f = loadstring(code)
+ if type(f) == "function" then
+ local buffer = {}
+ function mp.print(...)
+ mpprint(buffer,...)
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))
+ f()
+ return tableconcat(buffer,"")
end
+ return ""
end
% \end{macrocode}
-% Below code has been contributed by Dohyun Kim.
-% It implements |btex| / |etex| functions.
-%
-% v2.1: |textext()| is now available, which is equivalent to |TEX()| macro from TEX.mp.
-% |TEX()| is synonym of |textext()| unless TEX.mp is loaded.
-%
-% v2.2: Transparency and Shading
%
-% v2.3: \cs{everymplib}, \cs{everyendmplib},
-% and allows naked \TeX\ commands.
+% |make_text| must be one liner, so comment sign is not allowed.
% \begin{macrocode}
-local further_split_keys = {
- ["MPlibTEXboxID"] = true,
- ["sh_color_a"] = true,
- ["sh_color_b"] = true,
-}
+local function protecttexcontents (str)
+ return str:gsub("\\%%", "\0PerCent\0")
+ :gsub("%%.-\n", "")
+ :gsub("%%.-$", "")
+ :gsub("%zPerCent%z", "\\%%")
+ :gsub("%s+", " ")
+end
-local function script2table(s)
- local t = {}
- for _,i in ipairs(stringexplode(s,"\13+")) do
- local k,v = stringmatch(i,"(.-)=(.*)") -- v may contain = or empty.
- if k and v and k ~= "" then
- if further_split_keys[k] then
- t[k] = stringexplode(v,":")
- else
- t[k] = v
+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 t
+ return ""
end
+% \end{macrocode}
+%
+% Our MetaPost preambles
+% \begin{macrocode}
local mplibcodepreamble = [[
-vardef rawtextext (expr t) =
- if unknown TEXBOX_:
- image( special "MPlibmkTEXbox="&t;
- addto currentpicture doublepath unitsquare; )
- else:
- TEXBOX_ := TEXBOX_ + 1;
- if known TEXBOX_wd_[TEXBOX_]:
- image ( addto currentpicture doublepath unitsquare
- xscaled TEXBOX_wd_[TEXBOX_]
- yscaled (TEXBOX_ht_[TEXBOX_] + TEXBOX_dp_[TEXBOX_])
- shifted (0, -TEXBOX_dp_[TEXBOX_])
- withprescript "MPlibTEXboxID=" &
- decimal TEXBOX_ & ":" &
- decimal TEXBOX_wd_[TEXBOX_] & ":" &
- decimal(TEXBOX_ht_[TEXBOX_]+TEXBOX_dp_[TEXBOX_]); )
- else:
- image( special "MPlibTEXError=1"; )
- fi
- fi
-enddef;
+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;
@@ -1055,14 +1106,21 @@ def externalfigure primary filename =
draw rawtextext("\includegraphics{"& filename &"}")
enddef;
def TEX = textext enddef;
-def specialVerbatimTeX (text t) = special "MPlibVerbTeX="&t; enddef;
-def normalVerbatimTeX (text t) = special "PostMPlibVerbTeX="&t; enddef;
-let VerbatimTeX = specialVerbatimTeX;
-extra_beginfig := extra_beginfig & " let VerbatimTeX = normalVerbatimTeX;" ;
-extra_endfig := extra_endfig & " let VerbatimTeX = specialVerbatimTeX;" ;
]]
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 =
@@ -1076,150 +1134,241 @@ enddef;
]]
luamplib.textextlabelpreamble = textextlabelpreamble
-local TeX_code_t = {}
-local texboxnum = { 2047 }
-
-local function domakeTEXboxes (data)
- local num = texboxnum[1]
- texboxnum[2] = num
- local global = luamplib.globaltextext and "\\global" or ""
- if data and data.fig then
- local figures = data.fig
- for f=1, #figures do
- TeX_code_t[f] = nil
- local figure = figures[f]
- local objects = getobjects(data,figure,f)
- if objects then
- for o=1,#objects do
- local object = objects[o]
- local prescript = object.prescript
- prescript = prescript and script2table(prescript)
- local str = prescript and prescript.MPlibmkTEXbox
- if str then
- num = num + 1
- texsprint(format("%s\\setbox%i\\hbox{%s}", global, num, str))
- end
% \end{macrocode}
-% |verbatimtex ... etex| before |beginfig()| is not ignored,
-% but the \TeX\ code inbetween is inserted before the mplib box.
+%
+% When \cs{mplibverbatim} is enabled, do not expand |mplibcode| data.
% \begin{macrocode}
- local texcode = prescript and prescript.MPlibVerbTeX
- if texcode and texcode ~= "" then
- TeX_code_t[f] = texcode
- end
- end
- end
- end
+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
- if luamplib.globaltextext then
- texboxnum[1] = num
+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 protect_tex_text_common (data)
+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",everymplib, data, everyendmplib)
+ data = format("\n%s\n%s\n%s\n",everymplib, data, everyendmplib)
data = data:gsub("\r","\n")
- data = data:gsub("\"[^\n]-\"", function(str)
- return str:gsub("([bem])tex"..endname,"%1"..esctex)
- end)
+ data = data:gsub("\\mpcolor%s+(.-%b{})","mplibcolor(\"%1\")")
data = data:gsub(btex_etex, function(str)
- return format("rawtextext(\"%s\")",protecttexcontents(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\")",protecttexcontents(str))
+ return format("verbatimtex %s etex;", -- semicolon
+ luamplib.verbatiminput and str or protect_expansion(str))
end)
- return data
-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
-local function protecttextextVerbatim(data)
- data = protect_tex_text_common(data)
+ process(data)
+end
+luamplib.process_mplibcode = process_mplibcode
- data = data:gsub("\"[^\n]-\"", function(str) -- restore string btex .. etex
- return str:gsub("([bem])"..esctex, "%1tex")
- end)
+% \end{macrocode}
+%
+% For parsing |prescript| materials.
+% \begin{macrocode}
+local further_split_keys = {
+ ["mplibtexboxid"] = true,
+ ["sh_color_a"] = true,
+ ["sh_color_b"] = true,
+}
- local _,result = process(data, false)
- domakeTEXboxes(result)
- return data
+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
-luamplib.protecttextextVerbatim = protecttextextVerbatim
+% \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
-luamplib.mpxcolors = {}
+local function convert(result, flusher)
+ luamplib.flush(result, flusher)
+ return true -- done
+end
+luamplib.convert = convert
-local function protecttextext(data)
- data = protect_tex_text_common(data)
+local function pdf_startfigure(n,llx,lly,urx,ury)
+ texsprint(format("\\mplibstarttoPDF{%f}{%f}{%f}{%f}",llx,lly,urx,ury))
+end
- data = data:gsub("\"[^\n]-\"", function(str)
- str = str:gsub("([bem])"..esctex, "%1tex")
- :gsub("%%", escpcnt)
- :gsub("{", esclbr)
- :gsub("}", escrbr)
- :gsub("#", eschash)
- return format("\\detokenize{%s}",str)
- end)
+local function pdf_stopfigure()
+ texsprint("\\mplibstoptoPDF")
+end
- data = data:gsub("%%.-\n", "")
+% \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 grouplevel = tex.currentgrouplevel
- luamplib.mpxcolors[grouplevel] = {}
- data = data:gsub("\\mpcolor"..endname.."(.-){(.-)}", function(opt,str)
- local cnt = #luamplib.mpxcolors[grouplevel] + 1
- luamplib.mpxcolors[grouplevel][cnt] = format(
- "\\expandafter\\mplibcolor\\csname mpxcolor%i:%i\\endcsname%s{%s}",
- grouplevel,cnt,opt,str)
- return format("\\csname mpxcolor%i:%i\\endcsname",grouplevel,cnt)
+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
-% \end{macrocode}
-% Next line to address bug \#55
-% \begin{macrocode}
- data = data:gsub("([^`\\])#","%1##")
+local bend_tolerance = 131/65536
- texsprint(data)
+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
-luamplib.protecttextext = protecttextext
-
-local function makeTEXboxes (data)
- data = data:gsub("##","#")
- :gsub(escpcnt,"%%")
- :gsub(esclbr,"{")
- :gsub(escrbr,"}")
- :gsub(eschash,"#")
- local _,result = process(data, false)
- domakeTEXboxes(result)
- return data
+local function concat(px, py) -- no tx, ty here
+ return (sy*px-ry*py)/divider,(sx*py-rx*px)/divider
end
-luamplib.makeTEXboxes = makeTEXboxes
+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 factor = 65536*(7227/7200)
+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 processwithTEXboxes (data)
- if not data then return end
- local num = texboxnum[2]
- local prepreamble = format("TEXBOX_:=%i;\n",num)
- while true do
- num = num + 1
- local box = texgetbox(num)
- if not box then break end
- prepreamble = format(
- "%sTEXBOX_wd_[%i]:=%f;\nTEXBOX_ht_[%i]:=%f;\nTEXBOX_dp_[%i]:=%f;\n",
- prepreamble,
- num, box.width /factor,
- num, box.height/factor,
- num, box.depth /factor)
+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
- process(prepreamble .. data, true)
end
-luamplib.processwithTEXboxes = processwithTEXboxes
+% \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
@@ -1238,8 +1387,13 @@ local function stop_pdf_code()
end
end
-local function putTEXboxes (object,prescript)
- local box = prescript.MPlibTEXboxID
+% \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
@@ -1264,7 +1418,8 @@ local function putTEXboxes (object,prescript)
end
% \end{macrocode}
-% Transparency and Shading
+%
+% Colors and Transparency
% \begin{macrocode}
local pdf_objs = {}
local token, getpageres, setpageres = newtoken or token
@@ -1278,7 +1433,6 @@ else
"\\special{pdf:obj @MPlibSh<<>>}")
end
--- objstr <string> => obj <number>, new <boolean>
local function update_pdfobjs (os)
local on = pdf_objs[os]
if on then
@@ -1348,11 +1502,15 @@ local function tr_pdf_pageresources(mode,opaq)
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 and luatexbase.callbacktypes.finish_pdffile then -- ltluatex
+ 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()
@@ -1377,7 +1535,7 @@ local function sh_pdfpageresources(shtype,domain,colorspace,colora,colorb,coordi
shading_res[#shading_res+1] = res
else
local pageres = getpageres() or ""
- if not stringfind(pageres,"/Shading<<.*>>") then
+ if not pageres:find("/Shading<<.*>>") then
pageres = pageres.."/Shading<<>>"
end
pageres = pageres:gsub("/Shading<<","%1"..res)
@@ -1408,7 +1566,10 @@ end
local prev_override_color
local function do_preobj_color(object,prescript)
- -- transparency
+% \end{macrocode}
+%
+% transparency
+% \begin{macrocode}
local opaq = prescript and prescript.tr_transparency
local tron_no, troff_no
if opaq then
@@ -1417,7 +1578,10 @@ local function do_preobj_color(object,prescript)
tron_no, troff_no = tr_pdf_pageresources(mode,opaq)
pdf_literalcode("/MPlibTr%i gs",tron_no)
end
- -- color
+% \end{macrocode}
+%
+% color
+% \begin{macrocode}
local override = prescript and prescript.MPlibOverrideColor
if override then
if pdfmode then
@@ -1439,12 +1603,15 @@ local function do_preobj_color(object,prescript)
end
end
end
- -- shading
+% \end{macrocode}
+%
+% shading
+% \begin{macrocode}
local sh_type = prescript and prescript.sh_type
if sh_type then
local domain = prescript.sh_domain
- local centera = stringexplode(prescript.sh_center_a)
- local centerb = stringexplode(prescript.sh_center_b)
+ 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)
@@ -1501,10 +1668,9 @@ local function do_postobj_color(tr,over,sh)
end
% \end{macrocode}
-% End of |btex| -- |etex| and Transparency/Shading patch.
%
+% Finally, flush figures by inserting PDF literals.
% \begin{macrocode}
-
local function flush(result,flusher)
if result then
local figures = result.fig
@@ -1513,27 +1679,32 @@ local function flush(result,flusher)
info("flushing figure %s",f)
local figure = figures[f]
local objects = getobjects(result,figure,f)
- local fignum = tonumber(stringmatch(figure:filename(),"([%d]+)$") or figure:charcode() or 0)
+ 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}
-% \textsf{luamplib} silently ignores this invalid figure for those codes
+%
+% 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}
- -- invalid
- -- pdf_startfigure(fignum,0,0,0,0)
- -- pdf_stopfigure()
else
% \end{macrocode}
-% Insert |verbatimtex| code before mplib box.
-% And prepare for those codes that will be executed afterwards.
+%
+% For legacy behavior. Insert `pre-fig' \TeX\ code here, and
+% prepare a table for `in-fig' codes.
% \begin{macrocode}
- if TeX_code_t[f] then
- texsprint(TeX_code_t[f])
+ if tex_code_pre_mplib[f] then
+ texsprint(tex_code_pre_mplib[f])
end
- local TeX_code_bot = {} -- PostVerbatimTeX
+ local TeX_code_bot = {}
pdf_startfigure(fignum,llx,lly,urx,ury)
start_pdf_code()
if objects then
@@ -1543,20 +1714,16 @@ local function flush(result,flusher)
local object = objects[o]
local objecttype = object.type
% \end{macrocode}
-% Change from \ConTeXt{} code: the following 7 lines are part of the
-% |btex...etex| patch. Again, colors are processed at this stage.
-% Also, we collect \TeX\ codes that will be executed after flushing.
%
+% 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
- putTEXboxes(object,prescript)
- elseif prescript and prescript.PostMPlibVerbTeX then
- TeX_code_bot[#TeX_code_bot+1] = prescript.PostMPlibVerbTeX
- elseif objecttype == "start_bounds" or objecttype == "stop_bounds" then
- -- skip
+ 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()
@@ -1566,9 +1733,13 @@ local function flush(result,flusher)
stop_pdf_code()
miterlimit, linecap, linejoin, dashed = -1, -1, -1, false
elseif objecttype == "special" then
- -- not supported
- if prescript and prescript.MPlibTEXError then
- warn("textext() anomaly. Try disabling \\mplibtextextlabel.")
+% \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
@@ -1577,9 +1748,6 @@ local function flush(result,flusher)
pdf_textfigure(object.font,object.dsize,object.text,object.width,object.height,object.depth)
stop_pdf_code()
else
-% \end{macrocode}
-% Color stuffs are modified and moved to several lines above.
-% \begin{macrocode}
local evenodd, collect, both = false, false, false
local postscript = object.postscript
if not object.istext then
@@ -1666,10 +1834,9 @@ local function flush(result,flusher)
end
% \end{macrocode}
%
-% Change from \ConTeXt{} code: color stuff
-%
+% Change from ConTeXt general: there was color stuffs.
% \begin{macrocode}
- if not shade_no then ----- conflict with shading
+ 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
@@ -1723,18 +1890,15 @@ local function flush(result,flusher)
end
% \end{macrocode}
%
-% Added to \ConTeXt{} code: color stuff.
-% And execute |verbatimtex| codes.
-%
+% 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
+ if #TeX_code_bot > 0 then texsprint(TeX_code_bot) end
end
end
end
@@ -1764,6 +1928,7 @@ luamplib.colorconverter = colorconverter
%
% \subsection{\texorpdfstring{\TeX}{TeX} package}
%
+%
% \begin{macrocode}
%<*package>
% \end{macrocode}
@@ -1777,7 +1942,7 @@ luamplib.colorconverter = colorconverter
\else
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{luamplib}
- [2018/09/27 v2.12.5 mplib package for LuaTeX]
+ [2019/03/20 v2.20.0 mplib package for LuaTeX]
\ifx\newluafunction\@undefined
\input ltluatex
\fi
@@ -1785,12 +1950,11 @@ luamplib.colorconverter = colorconverter
% \end{macrocode}
%
% Loading of lua code.
-%
% \begin{macrocode}
\directlua{require("luamplib")}
% \end{macrocode}
%
-% Support older formats
+% Support older engine. Seems we don't need it, but no harm.
% \begin{macrocode}
\ifx\scantextokens\undefined
\let\scantextokens\luatexscantextokens
@@ -1798,20 +1962,18 @@ luamplib.colorconverter = colorconverter
\ifx\pdfoutput\undefined
\let\pdfoutput\outputmode
\protected\def\pdfliteral{\pdfextension literal}
+ \def\pdffontsize{\dimexpr\pdffeedback fontsize\relax}
\fi
% \end{macrocode}
-
%
% Set the format for metapost.
-%
% \begin{macrocode}
\def\mplibsetformat#1{\directlua{luamplib.setformat("#1")}}
% \end{macrocode}
%
-% \textsf{luamplib} works in both PDF and DVI mode,
+% 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
@@ -1825,17 +1987,32 @@ luamplib.colorconverter = colorconverter
\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{%
- %catcode`\{=12 %catcode`\}=12
+ \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 }
@@ -1846,7 +2023,6 @@ luamplib.colorconverter = colorconverter
% \end{macrocode}
%
% The Plain-specific stuff.
-%
% \begin{macrocode}
\bgroup\expandafter\expandafter\expandafter\egroup
\expandafter\ifx\csname selectfont\endcsname\relax
@@ -1863,23 +2039,14 @@ luamplib.colorconverter = colorconverter
}
\long\def\mplibdocode#1\endmplibcode{%
\endgroup
- \ifdefined\mplibverbatimYes
- \directlua{luamplib.tempdata\the\currentgrouplevel=luamplib.protecttextextVerbatim([===[\detokenize{#1}]===])}%
- \directlua{luamplib.processwithTEXboxes(luamplib.tempdata\the\currentgrouplevel)}%
- \else
- \edef\mplibtemp{\directlua{luamplib.protecttextext([===[\unexpanded{#1}]===])}}%
- \directlua{ tex.sprint(luamplib.mpxcolors[\the\currentgrouplevel]) }%
- \directlua{luamplib.tempdata\the\currentgrouplevel=luamplib.makeTEXboxes([===[\mplibtemp]===])}%
- \directlua{luamplib.processwithTEXboxes(luamplib.tempdata\the\currentgrouplevel)}%
- \fi
+ \directlua{luamplib.process_mplibcode([===[\unexpanded{#1}]===])}%
\endgroup
\ifnum\mplibstartlineno<\inputlineno\expandafter\mplibreplacenewlinecs\fi
}
\else
% \end{macrocode}
%
-% The \LaTeX-specific parts: a new environment.
-%
+% The \LaTeX-specific part: a new environment.
% \begin{macrocode}
\newenvironment{mplibcode}{%
\global\mplibstartlineno\inputlineno
@@ -1894,16 +2061,9 @@ luamplib.colorconverter = colorconverter
\long\def\ltxdomplibcodeindeed#1\end#2{%
\endgroup
\toks@\expandafter{\the\toks@#1}%
- \def\mplibtemp@a{#2}\ifx\mplib@mplibcode\mplibtemp@a
- \ifdefined\mplibverbatimYes
- \directlua{luamplib.tempdata\the\currentgrouplevel=luamplib.protecttextextVerbatim([===[\the\toks@]===])}%
- \directlua{luamplib.processwithTEXboxes(luamplib.tempdata\the\currentgrouplevel)}%
- \else
- \edef\mplibtemp{\directlua{luamplib.protecttextext([===[\the\toks@]===])}}%
- \directlua{ tex.sprint(luamplib.mpxcolors[\the\currentgrouplevel]) }%
- \directlua{luamplib.tempdata\the\currentgrouplevel=luamplib.makeTEXboxes([===[\mplibtemp]===])}%
- \directlua{luamplib.processwithTEXboxes(luamplib.tempdata\the\currentgrouplevel)}%
- \fi
+ \def\mplibtemp@a{#2}%
+ \ifx\mplib@mplibcode\mplibtemp@a
+ \directlua{luamplib.process_mplibcode([===[\the\toks@]===])}%
\end{mplibcode}%
\ifnum\mplibstartlineno<\inputlineno
\expandafter\expandafter\expandafter\mplibreplacenewlinebr
@@ -1913,22 +2073,32 @@ luamplib.colorconverter = colorconverter
\fi
}
\fi
-\def\mplibverbatim#1{%
- \begingroup
- \def\mplibtempa{#1}\def\mplibtempb{enable}%
- \expandafter\endgroup
- \ifx\mplibtempa\mplibtempb
- \let\mplibverbatimYes\relax
- \else
- \let\mplibverbatimYes\undefined
- \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{%
@@ -1953,18 +2123,24 @@ luamplib.colorconverter = colorconverter
\everyendmplibtoks{#1}%
\ifnum\mplibstartlineno<\inputlineno\expandafter\mplibreplacenewlinebr\fi
}
+% \end{macrocode}
+%
+% Allow \TeX\ dimen macros in |mplibcode|.
+% \begin{macrocode}
\def\mpdim#1{ begingroup \the\dimexpr #1\relax\space endgroup } % gmp.sty
% \end{macrocode}
%
-% Support color/xcolor packages.
-% User interface is: |\mpcolor{teal}| or |\mpcolor[HTML]{008080}|,
-% for example.
+% 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\mplibcolor#1{%
- \def\set@color{\edef#1{1 withprescript "MPlibOverrideColor=\current@color"}}%
- \color
-}
-\def\mplibnumbersystem#1{\directlua{luamplib.numbersystem = "#1"}}
\def\mplibmakenocache#1{\mplibdomakenocache #1,*,}
\def\mplibdomakenocache#1,{%
\ifx\empty#1\empty
@@ -1988,46 +2164,43 @@ luamplib.colorconverter = colorconverter
\fi
}
\def\mplibcachedir#1{\directlua{luamplib.getcachedir("\unexpanded{#1}")}}
-\def\mplibtextextlabel#1{%
- \begingroup
- \def\tempa{enable}\def\tempb{#1}%
- \ifx\tempa\tempb
- \directlua{luamplib.textextlabel = true}%
- \else
- \directlua{luamplib.textextlabel = false}%
- \fi
- \endgroup
-}
-\def\mplibcodeinherit#1{%
- \begingroup
- \def\tempa{enable}\def\tempb{#1}%
- \ifx\tempa\tempb
- \directlua{luamplib.codeinherit = true}%
- \else
- \directlua{luamplib.codeinherit = false}%
- \fi
- \endgroup
-}
-\def\mplibglobaltextext#1{%
- \begingroup
- \def\tempa{enable}\def\tempb{#1}%
- \ifx\tempa\tempb
- \directlua{luamplib.globaltextext = true}%
- \else
- \directlua{luamplib.globaltextext = false}%
- \fi
- \endgroup
-}
% \end{macrocode}
%
-% We use a dedicated scratchbox.
+% 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
@@ -2042,9 +2215,6 @@ luamplib.colorconverter = colorconverter
\setbox\mplibscratchbox\vbox\bgroup
\noindent
}
-% \end{macrocode}
-%
-% \begin{macrocode}
\def\mplibstoptoPDF{%
\egroup %
\setbox\mplibscratchbox\hbox %
@@ -2066,7 +2236,6 @@ luamplib.colorconverter = colorconverter
% \end{macrocode}
%
% Text items have a special handler.
-%
% \begin{macrocode}
\def\mplibtextext#1#2#3#4#5{%
\begingroup
@@ -2086,8 +2255,7 @@ luamplib.colorconverter = colorconverter
}
% \end{macrocode}
%
-% input luamplib.cfg when it exists
-%
+% Input |luamplib.cfg| when it exists.
% \begin{macrocode}
\openin0=luamplib.cfg
\ifeof0 \else
diff --git a/Master/texmf-dist/tex/luatex/luamplib/luamplib.lua b/Master/texmf-dist/tex/luatex/luamplib/luamplib.lua
index 73449b7be97..c94fb761fc9 100644
--- a/Master/texmf-dist/tex/luatex/luamplib/luamplib.lua
+++ b/Master/texmf-dist/tex/luatex/luamplib/luamplib.lua
@@ -9,32 +9,25 @@
-- See source file 'luamplib.dtx' for licencing and contact information.
--
-luamplib = luamplib or { }
-
-
-local luamplib = luamplib
-luamplib.showlog = luamplib.showlog or false
-luamplib.lastlog = ""
-
luatexbase.provides_module {
name = "luamplib",
- version = "2.12.5",
- date = "2018/09/27",
+ version = "2.20.0",
+ date = "2019/03/20",
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
-local stringgsub = string.gsub
-local stringfind = string.find
-local stringmatch = string.match
-local stringgmatch = string.gmatch
-local stringexplode = string.explode
+luamplib = luamplib or { }
+local luamplib = luamplib
+
+luamplib.showlog = luamplib.showlog or false
+luamplib.lastlog = ""
+
local tableconcat = table.concat
local texsprint = tex.sprint
local textprint = tex.tprint
@@ -42,6 +35,12 @@ local textprint = tex.tprint
local texget = tex.get
local texgettoks = tex.gettoks
local texgetbox = tex.getbox
+local texruntoks = tex.runtoks
+local texscantoks = tex.scantoks
+
+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')
@@ -55,10 +54,10 @@ local ioopen = io.open
local file = file or { }
local replacesuffix = file.replacesuffix or function(filename, suffix)
- return (stringgsub(filename,"%.[%a%d]+$","")) .. "." .. suffix
+ return (filename:gsub("%.[%a%d]+$","")) .. "." .. suffix
end
local stripsuffix = file.stripsuffix or function(filename)
- return (stringgsub(filename,"%.[%a%d]+$",""))
+ return (filename:gsub("%.[%a%d]+$",""))
end
local is_writable = file.is_writable or function(name)
@@ -73,7 +72,7 @@ local is_writable = file.is_writable or function(name)
end
local mk_full_path = lfs.mkdirs or function(path)
local full = ""
- for sub in stringgmatch(path,"(/*[^\\/]+)") do
+ for sub in path:gmatch("(/*[^\\/]+)") do
full = full .. sub
lfsmkdir(full)
end
@@ -88,7 +87,7 @@ local outputdir
if lfstouch then
local texmfvar = kpse.expand_var('$TEXMFVAR')
if texmfvar and texmfvar ~= "" and texmfvar ~= '$TEXMFVAR' then
- for _,dir in next,stringexplode(texmfvar,os.type == "windows" and ";" or ":") do
+ for _,dir in next, texmfvar:explode(os.type == "windows" and ";" or ":") do
if not lfsisdir(dir) then
mk_full_path(dir)
end
@@ -104,7 +103,7 @@ end
if not outputdir then
outputdir = "."
for _,v in ipairs(arg) do
- local t = stringmatch(v,"%-output%-directory=(.+)")
+ local t = v:match("%-output%-directory=(.+)")
if t then
outputdir = t
break
@@ -130,43 +129,19 @@ function luamplib.getcachedir(dir)
end
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-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,
+ ["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
@@ -189,25 +164,10 @@ local function replaceformatmp(file,newfile,ofmodify)
return newfile
end
-local esctex = "!!!T!!!E!!!X!!!"
-local esclbr = "!!!!!LEFTBRCE!!!!!"
-local escrbr = "!!!!!RGHTBRCE!!!!!"
-local escpcnt = "!!!!!PERCENT!!!!!"
-local eschash = "!!!!!HASH!!!!!"
-local begname = "%f[A-Z_a-z]"
-local endname = "%f[^A-Z_a-z]"
-
-local btex_etex = begname.."btex"..endname.."%s*(.-)%s*"..begname.."etex"..endname
-local verbatimtex_etex = begname.."verbatimtex"..endname.."%s*(.-)%s*"..begname.."etex"..endname
-
-local function protecttexcontents(str)
- return str:gsub("\\%%", "\\"..escpcnt)
- :gsub("%%.-\n", "")
- :gsub("%%.-$", "")
- :gsub('"', '"&ditto&"')
- :gsub("\n%s*", " ")
- :gsub(escpcnt, "%%")
-end
+local name_b = "%f[A-Z_a-z]"
+local name_e = "%f[^A-Z_a-z]"
+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")
@@ -217,10 +177,12 @@ local function replaceinputmpfile (name,file)
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
+ 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")
@@ -228,22 +190,11 @@ local function replaceinputmpfile (name,file)
local data = fh:read("*all"); fh:close()
local count,cnt = 0,0
-
- data = data:gsub("\"[^\n]-\"", function(str)
- return str:gsub("([bem])tex"..endname,"%1"..esctex)
- end)
-
- data, cnt = data:gsub(btex_etex, function(str)
- return format("rawtextext(\"%s\")",protecttexcontents(str))
- end)
+ data, cnt = data:gsub(btex_etex, "btex %1 etex ") -- space
count = count + cnt
- data, cnt = data:gsub(verbatimtex_etex, "")
+ data, cnt = data:gsub(verbatimtex_etex, "verbatimtex %1 etex;") -- semicolon
count = count + cnt
- data = data:gsub("\"[^\n]-\"", function(str) -- restore string btex .. etex
- return str:gsub("([bem])"..esctex, "%1tex")
- end)
-
if count == 0 then
noneedtoreplace[name] = true
fh = ioopen(newfile,"w");
@@ -253,6 +204,7 @@ local function replaceinputmpfile (name,file)
end
return file
end
+
fh = ioopen(newfile,"w")
if not fh then return file end
fh:write(data); fh:close()
@@ -260,8 +212,6 @@ local function replaceinputmpfile (name,file)
return newfile
end
-local randomseed = nil
-
local mpkpse = kpse.new(arg[0], "mpost")
local special_ftype = {
@@ -281,105 +231,35 @@ local function finder(name, mode, ftype)
end
return replaceinputmpfile(name,file)
end
- return mpkpse:find_file(name,stringmatch(name,"[a-zA-Z]+$"))
+ return mpkpse:find_file(name, name:match("[a-zA-Z]+$"))
end
end
luamplib.finder = finder
-
-function luamplib.resetlastlog()
- luamplib.lastlog = ""
+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 mplibone = tonumber(mplib.version()) <= 1.50
-
-if mplibone then
-
- luamplib.make = luamplib.make or function(name,mem_name,dump)
- local t = os.clock()
- local mpx = mplib.new {
- ini_version = true,
- find_file = luamplib.finder,
- job_name = stripsuffix(name)
- }
- mpx:execute(format("input %s ;",name))
- if dump then
- mpx:execute("dump ;")
- info("format %s made and dumped for %s in %0.3f seconds",mem_name,name,os.clock()-t)
- else
- info("%s read in %0.3f seconds",name,os.clock()-t)
- end
- return mpx
- end
-
- function luamplib.load(name)
- local mem_name = replacesuffix(name,"mem")
- local mpx = mplib.new {
- ini_version = false,
- mem_name = mem_name,
- find_file = luamplib.finder
- }
- if not mpx and type(luamplib.make) == "function" then
- -- when i have time i'll locate the format and dump
- mpx = luamplib.make(name,mem_name)
- end
- if mpx then
- info("using format %s",mem_name,false)
- return mpx, nil
- else
- return nil, { status = 99, error = "out of memory or invalid format" }
- end
- end
-
-else
-
- local preamble = [[
- boolean mplib ; mplib := true ;
- let dump = endinput ;
- let normalfontsize = fontsize;
- input %s ;
- ]]
-
- luamplib.make = luamplib.make or function()
- end
-
- function luamplib.load(name,verbatim)
- local mpx = mplib.new {
- ini_version = true,
- find_file = luamplib.finder,
- math_mode = luamplib.numbersystem,
- random_seed = randomseed,
- }
- local preamble = preamble .. (verbatim and "" or luamplib.mplibcodepreamble)
- if luamplib.textextlabel then
- preamble = preamble .. (verbatim and "" or 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
- luamplib.reporterror(result)
- return mpx, result
- end
-
-end
-
-local currentformat = "plain"
+local preamble = [[
+ boolean mplib ; mplib := true ;
+ let dump = endinput ;
+ let normalfontsize = fontsize;
+ input %s ;
+]]
-local function setformat (name) --- used in .sty
- currentformat = name
+local function luamplibresetlastlog()
+ luamplib.lastlog = ""
end
-luamplib.setformat = setformat
-luamplib.reporterror = function (result)
+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 = stringgsub(t or l or "no-term","^%s+","\n")
- luamplib.lastlog = luamplib.lastlog .. "\n " .. (l or t or "no-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
@@ -390,17 +270,50 @@ luamplib.reporterror = function (result)
end
end
-local function process_indeed (mpx, data, indeed)
+local function luamplibload (name)
+ local mpx = mplib.new {
+ ini_version = true,
+ find_file = luamplib.finder,
+ make_text = luamplib.maketext,
+ run_script = luamplib.runscript,
+ math_mode = luamplib.numbersystem,
+ extensions = 1,
+ }
+ 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
+
+local currentformat = "plain"
+
+local function setformat (name)
+ currentformat = name
+end
+luamplib.setformat = setformat
+
+local function process_indeed (mpx, data)
local converted, result = false, {}
if mpx and data then
result = mpx:execute(data)
- local log = luamplib.reporterror(result)
- if indeed and log then
+ local log = reporterror(result)
+ if log then
if luamplib.showlog then
info("%s",luamplib.lastlog)
- luamplib.resetlastlog()
+ luamplibresetlastlog()
elseif result.fig then
- if stringfind(log,"\n>>") then info("%s",log) end
+ if log:find("\n>>") then info("%s",log) end
converted = luamplib.convert(result)
else
info("%s",log)
@@ -415,182 +328,206 @@ end
luamplib.codeinherit = false
local mplibinstances = {}
-local process = function (data,indeed,verbatim)
- if not stringfind(data, begname.."beginfig%s*%([%+%-%s]*%d[%.%d%s]*%)") then
+
+local function process (data)
+ if not data:find(name_b.."beginfig%s*%([%+%-%s]*%d[%.%d%s]*%)") then
data = data .. "beginfig(-1);endfig;"
end
- local standalone, firstpass = not luamplib.codeinherit, not indeed
+ local standalone = not luamplib.codeinherit
local currfmt = currentformat .. (luamplib.numbersystem or "scaled")
- currfmt = firstpass and currfmt or (currfmt.."2")
+ .. 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
- randomseed = firstpass and math.random(65535) or randomseed
- mpx = luamplib.load(currentformat,verbatim)
+ mpx = luamplibload(currentformat)
mplibinstances[currfmt] = mpx
end
- return process_indeed(mpx, data, indeed)
+ return process_indeed(mpx, data)
end
-luamplib.process = process
-local function getobjects(result,figure,f)
- return figure:objects()
-end
+local catlatex = luatexbase.registernumber("catcodetable@latex")
+local catat11 = luatexbase.registernumber("catcodetable@atletter")
-local function convert(result, flusher)
- luamplib.flush(result, flusher)
- return true -- done
+local function run_tex_code_no_use (str, cat)
+ cat = cat or catlatex
+ texscantoks("mplibtmptoks", cat, str)
+ texruntoks("mplibtmptoks")
end
-luamplib.convert = convert
-local function pdf_startfigure(n,llx,lly,urx,ury)
- texsprint(format("\\mplibstarttoPDF{%f}{%f}{%f}{%f}",llx,lly,urx,ury))
+local function run_tex_code (str, cat)
+ cat = cat or catlatex
+ texruntoks(function() texsprint(cat, str) end)
end
-local function pdf_stopfigure()
- texsprint("\\mplibstoptoPDF")
+local tex_box_id = 2047
+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
-local function pdf_literalcode(fmt,...) -- table
- textprint({"\\mplibtoPDF{"},{-2,format(fmt,...)},{"}"})
+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
-luamplib.pdf_literalcode = pdf_literalcode
-local function pdf_textfigure(font,size,text,width,height,depth)
- -- if text == "" then text = "\0" end -- char(0) has gone
- 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))
+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
-luamplib.pdf_textfigure = pdf_textfigure
-local bend_tolerance = 131/65536
+local function process_verbatimtex_text (str)
+ if str then
+ run_tex_code(str)
+ end
+ return ""
+end
-local rx, sx, sy, ry, tx, ty, divider = 1, 0, 0, 1, 0, 0, 1
+local tex_code_pre_mplib = {}
+luamplib.figid = 1
+luamplib.in_the_fig = false
-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
+local function legacy_mplibcode_reset ()
+ tex_code_pre_mplib = {}
+ luamplib.figid = 1
end
-local function concat(px, py) -- no tx, ty here
- return (sy*px-ry*py)/divider,(sx*py-rx*px)/divider
+local function process_verbatimtex_prefig (str)
+ if str then
+ tex_code_pre_mplib[luamplib.figid] = str
+ end
+ return ""
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
+local function process_verbatimtex_infig (str)
+ if str then
+ return format("special \"postmplibverbtex=%s\";", str)
end
- return true
+ return ""
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)
+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,
+}
+
+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
+LUATEXFUNCTIONALITY = LUATEXFUNCTIONALITY or 0
+
+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] = "(" .. concat(value,",") .. ")"
+ else -- boolean or whatever
+ buffer[#buffer+1] = tostring(value)
+ end
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))
+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
- 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))
+ local f = loadstring(code)
+ if type(f) == "function" then
+ local buffer = {}
+ function mp.print(...)
+ mpprint(buffer,...)
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))
+ f()
+ return tableconcat(buffer,"")
end
+ return ""
end
-local further_split_keys = {
- ["MPlibTEXboxID"] = true,
- ["sh_color_a"] = true,
- ["sh_color_b"] = true,
-}
+local function protecttexcontents (str)
+ return str:gsub("\\%%", "\0PerCent\0")
+ :gsub("%%.-\n", "")
+ :gsub("%%.-$", "")
+ :gsub("%zPerCent%z", "\\%%")
+ :gsub("%s+", " ")
+end
-local function script2table(s)
- local t = {}
- for _,i in ipairs(stringexplode(s,"\13+")) do
- local k,v = stringmatch(i,"(.-)=(.*)") -- v may contain = or empty.
- if k and v and k ~= "" then
- if further_split_keys[k] then
- t[k] = stringexplode(v,":")
- else
- t[k] = v
+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 t
+ return ""
end
local mplibcodepreamble = [[
-vardef rawtextext (expr t) =
- if unknown TEXBOX_:
- image( special "MPlibmkTEXbox="&t;
- addto currentpicture doublepath unitsquare; )
- else:
- TEXBOX_ := TEXBOX_ + 1;
- if known TEXBOX_wd_[TEXBOX_]:
- image ( addto currentpicture doublepath unitsquare
- xscaled TEXBOX_wd_[TEXBOX_]
- yscaled (TEXBOX_ht_[TEXBOX_] + TEXBOX_dp_[TEXBOX_])
- shifted (0, -TEXBOX_dp_[TEXBOX_])
- withprescript "MPlibTEXboxID=" &
- decimal TEXBOX_ & ":" &
- decimal TEXBOX_wd_[TEXBOX_] & ":" &
- decimal(TEXBOX_ht_[TEXBOX_]+TEXBOX_dp_[TEXBOX_]); )
- else:
- image( special "MPlibTEXError=1"; )
- fi
- fi
-enddef;
+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;
@@ -620,14 +557,21 @@ def externalfigure primary filename =
draw rawtextext("\includegraphics{"& filename &"}")
enddef;
def TEX = textext enddef;
-def specialVerbatimTeX (text t) = special "MPlibVerbTeX="&t; enddef;
-def normalVerbatimTeX (text t) = special "PostMPlibVerbTeX="&t; enddef;
-let VerbatimTeX = specialVerbatimTeX;
-extra_beginfig := extra_beginfig & " let VerbatimTeX = normalVerbatimTeX;" ;
-extra_endfig := extra_endfig & " let VerbatimTeX = specialVerbatimTeX;" ;
]]
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 =
@@ -641,142 +585,199 @@ enddef;
]]
luamplib.textextlabelpreamble = textextlabelpreamble
-local TeX_code_t = {}
-local texboxnum = { 2047 }
-
-local function domakeTEXboxes (data)
- local num = texboxnum[1]
- texboxnum[2] = num
- local global = luamplib.globaltextext and "\\global" or ""
- if data and data.fig then
- local figures = data.fig
- for f=1, #figures do
- TeX_code_t[f] = nil
- local figure = figures[f]
- local objects = getobjects(data,figure,f)
- if objects then
- for o=1,#objects do
- local object = objects[o]
- local prescript = object.prescript
- prescript = prescript and script2table(prescript)
- local str = prescript and prescript.MPlibmkTEXbox
- if str then
- num = num + 1
- texsprint(format("%s\\setbox%i\\hbox{%s}", global, num, str))
- end
- local texcode = prescript and prescript.MPlibVerbTeX
- if texcode and texcode ~= "" then
- TeX_code_t[f] = texcode
- end
- end
- end
- end
+luamplib.verbatiminput = false
+
+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
- if luamplib.globaltextext then
- texboxnum[1] = num
+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 protect_tex_text_common (data)
+local function process_mplibcode (data)
+ legacy_mplibcode_reset()
+
local everymplib = texgettoks('everymplibtoks') or ''
local everyendmplib = texgettoks('everyendmplibtoks') or ''
- data = format("\n%s\n%s\n%s",everymplib, data, everyendmplib)
+ data = format("\n%s\n%s\n%s\n",everymplib, data, everyendmplib)
data = data:gsub("\r","\n")
- data = data:gsub("\"[^\n]-\"", function(str)
- return str:gsub("([bem])tex"..endname,"%1"..esctex)
- end)
+ data = data:gsub("\\mpcolor%s+(.-%b{})","mplibcolor(\"%1\")")
data = data:gsub(btex_etex, function(str)
- return format("rawtextext(\"%s\")",protecttexcontents(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\")",protecttexcontents(str))
+ return format("verbatimtex %s etex;", -- semicolon
+ luamplib.verbatiminput and str or protect_expansion(str))
end)
- return data
-end
+ 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)
+ 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
-local function protecttextextVerbatim(data)
- data = protect_tex_text_common(data)
+ process(data)
+end
+luamplib.process_mplibcode = process_mplibcode
- data = data:gsub("\"[^\n]-\"", function(str) -- restore string btex .. etex
- return str:gsub("([bem])"..esctex, "%1tex")
- end)
+local further_split_keys = {
+ ["mplibtexboxid"] = true,
+ ["sh_color_a"] = true,
+ ["sh_color_b"] = true,
+}
- local _,result = process(data, false)
- domakeTEXboxes(result)
- return data
+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
-luamplib.protecttextextVerbatim = protecttextextVerbatim
+local function getobjects(result,figure,f)
+ return figure:objects()
+end
-luamplib.mpxcolors = {}
+local function convert(result, flusher)
+ luamplib.flush(result, flusher)
+ return true -- done
+end
+luamplib.convert = convert
-local function protecttextext(data)
- data = protect_tex_text_common(data)
+local function pdf_startfigure(n,llx,lly,urx,ury)
+ texsprint(format("\\mplibstarttoPDF{%f}{%f}{%f}{%f}",llx,lly,urx,ury))
+end
- data = data:gsub("\"[^\n]-\"", function(str)
- str = str:gsub("([bem])"..esctex, "%1tex")
- :gsub("%%", escpcnt)
- :gsub("{", esclbr)
- :gsub("}", escrbr)
- :gsub("#", eschash)
- return format("\\detokenize{%s}",str)
- end)
+local function pdf_stopfigure()
+ texsprint("\\mplibstoptoPDF")
+end
- data = data:gsub("%%.-\n", "")
+local function pdf_literalcode(fmt,...) -- table
+ textprint({"\\mplibtoPDF{"},{-2,format(fmt,...)},{"}"})
+end
- local grouplevel = tex.currentgrouplevel
- luamplib.mpxcolors[grouplevel] = {}
- data = data:gsub("\\mpcolor"..endname.."(.-){(.-)}", function(opt,str)
- local cnt = #luamplib.mpxcolors[grouplevel] + 1
- luamplib.mpxcolors[grouplevel][cnt] = format(
- "\\expandafter\\mplibcolor\\csname mpxcolor%i:%i\\endcsname%s{%s}",
- grouplevel,cnt,opt,str)
- return format("\\csname mpxcolor%i:%i\\endcsname",grouplevel,cnt)
+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
- data = data:gsub("([^`\\])#","%1##")
+local rx, sx, sy, ry, tx, ty, divider = 1, 0, 0, 1, 0, 0, 1
- texsprint(data)
+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
-luamplib.protecttextext = protecttextext
-
-local function makeTEXboxes (data)
- data = data:gsub("##","#")
- :gsub(escpcnt,"%%")
- :gsub(esclbr,"{")
- :gsub(escrbr,"}")
- :gsub(eschash,"#")
- local _,result = process(data, false)
- domakeTEXboxes(result)
- return data
+local function concat(px, py) -- no tx, ty here
+ return (sy*px-ry*py)/divider,(sx*py-rx*px)/divider
end
-luamplib.makeTEXboxes = makeTEXboxes
+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 factor = 65536*(7227/7200)
+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 processwithTEXboxes (data)
- if not data then return end
- local num = texboxnum[2]
- local prepreamble = format("TEXBOX_:=%i;\n",num)
- while true do
- num = num + 1
- local box = texgetbox(num)
- if not box then break end
- prepreamble = format(
- "%sTEXBOX_wd_[%i]:=%f;\nTEXBOX_ht_[%i]:=%f;\nTEXBOX_dp_[%i]:=%f;\n",
- prepreamble,
- num, box.width /factor,
- num, box.height/factor,
- num, box.depth /factor)
+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
- process(prepreamble .. data, true)
end
-luamplib.processwithTEXboxes = processwithTEXboxes
local pdfoutput = tonumber(texget("outputmode")) or tonumber(texget("pdfoutput"))
local pdfmode = pdfoutput > 0
@@ -796,8 +797,8 @@ local function stop_pdf_code()
end
end
-local function putTEXboxes (object,prescript)
- local box = prescript.MPlibTEXboxID
+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
@@ -833,7 +834,6 @@ else
"\\special{pdf:obj @MPlibSh<<>>}")
end
--- objstr <string> => obj <number>, new <boolean>
local function update_pdfobjs (os)
local on = pdf_objs[os]
if on then
@@ -907,7 +907,7 @@ local shading_res
local function shading_initialize ()
shading_res = {}
- if pdfmode and luatexbase.callbacktypes and luatexbase.callbacktypes.finish_pdffile then -- ltluatex
+ 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()
@@ -932,7 +932,7 @@ local function sh_pdfpageresources(shtype,domain,colorspace,colora,colorb,coordi
shading_res[#shading_res+1] = res
else
local pageres = getpageres() or ""
- if not stringfind(pageres,"/Shading<<.*>>") then
+ if not pageres:find("/Shading<<.*>>") then
pageres = pageres.."/Shading<<>>"
end
pageres = pageres:gsub("/Shading<<","%1"..res)
@@ -963,7 +963,6 @@ end
local prev_override_color
local function do_preobj_color(object,prescript)
- -- transparency
local opaq = prescript and prescript.tr_transparency
local tron_no, troff_no
if opaq then
@@ -972,7 +971,6 @@ local function do_preobj_color(object,prescript)
tron_no, troff_no = tr_pdf_pageresources(mode,opaq)
pdf_literalcode("/MPlibTr%i gs",tron_no)
end
- -- color
local override = prescript and prescript.MPlibOverrideColor
if override then
if pdfmode then
@@ -994,12 +992,11 @@ local function do_preobj_color(object,prescript)
end
end
end
- -- shading
local sh_type = prescript and prescript.sh_type
if sh_type then
local domain = prescript.sh_domain
- local centera = stringexplode(prescript.sh_center_a)
- local centerb = stringexplode(prescript.sh_center_b)
+ 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)
@@ -1055,7 +1052,6 @@ local function do_postobj_color(tr,over,sh)
end
end
-
local function flush(result,flusher)
if result then
local figures = result.fig
@@ -1064,19 +1060,16 @@ local function flush(result,flusher)
info("flushing figure %s",f)
local figure = figures[f]
local objects = getobjects(result,figure,f)
- local fignum = tonumber(stringmatch(figure:filename(),"([%d]+)$") or figure:charcode() or 0)
+ 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
- -- invalid
- -- pdf_startfigure(fignum,0,0,0,0)
- -- pdf_stopfigure()
else
- if TeX_code_t[f] then
- texsprint(TeX_code_t[f])
+ if tex_code_pre_mplib[f] then
+ texsprint(tex_code_pre_mplib[f])
end
- local TeX_code_bot = {} -- PostVerbatimTeX
+ local TeX_code_bot = {}
pdf_startfigure(fignum,llx,lly,urx,ury)
start_pdf_code()
if objects then
@@ -1088,12 +1081,9 @@ local function flush(result,flusher)
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
- putTEXboxes(object,prescript)
- elseif prescript and prescript.PostMPlibVerbTeX then
- TeX_code_bot[#TeX_code_bot+1] = prescript.PostMPlibVerbTeX
- elseif objecttype == "start_bounds" or objecttype == "stop_bounds" then
- -- skip
+ 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()
@@ -1103,9 +1093,8 @@ local function flush(result,flusher)
stop_pdf_code()
miterlimit, linecap, linejoin, dashed = -1, -1, -1, false
elseif objecttype == "special" then
- -- not supported
- if prescript and prescript.MPlibTEXError then
- warn("textext() anomaly. Try disabling \\mplibtextextlabel.")
+ 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
@@ -1198,7 +1187,7 @@ local function flush(result,flusher)
else
flushnormalpath(path,open)
end
- if not shade_no then ----- conflict with shading
+ 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
@@ -1255,9 +1244,7 @@ local function flush(result,flusher)
end
stop_pdf_code()
pdf_stopfigure()
- if #TeX_code_bot > 0 then
- texsprint(TeX_code_bot)
- end
+ if #TeX_code_bot > 0 then texsprint(TeX_code_bot) end
end
end
end
diff --git a/Master/texmf-dist/tex/luatex/luamplib/luamplib.sty b/Master/texmf-dist/tex/luatex/luamplib/luamplib.sty
index fa85ecc852a..dfca44a5c3e 100644
--- a/Master/texmf-dist/tex/luatex/luamplib/luamplib.sty
+++ b/Master/texmf-dist/tex/luatex/luamplib/luamplib.sty
@@ -14,7 +14,7 @@
\else
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{luamplib}
- [2018/09/27 v2.12.5 mplib package for LuaTeX]
+ [2019/03/20 v2.20.0 mplib package for LuaTeX]
\ifx\newluafunction\@undefined
\input ltluatex
\fi
@@ -26,8 +26,8 @@
\ifx\pdfoutput\undefined
\let\pdfoutput\outputmode
\protected\def\pdfliteral{\pdfextension literal}
+ \def\pdffontsize{\dimexpr\pdffeedback fontsize\relax}
\fi
-
\def\mplibsetformat#1{\directlua{luamplib.setformat("#1")}}
\ifnum\pdfoutput>0
\let\mplibtoPDF\pdfliteral
@@ -41,8 +41,11 @@
\write128{}
\fi
\fi
+\def\mplibforcehmode{\let\mplibhmodeornot\leavevmode}
+\def\mplibnoforcehmode{\let\mplibhmodeornot\relax}
+\mplibnoforcehmode
\def\mplibsetupcatcodes{%
- %catcode`\{=12 %catcode`\}=12
+ \mplibhmodeornot %catcode`\{=12 %catcode`\}=12
\catcode`\#=12 \catcode`\^=12 \catcode`\~=12 \catcode`\_=12
\catcode`\&=12 \catcode`\$=12 \catcode`\%=12 \catcode`\^^M=12 \endlinechar=10
}
@@ -69,15 +72,7 @@
}
\long\def\mplibdocode#1\endmplibcode{%
\endgroup
- \ifdefined\mplibverbatimYes
- \directlua{luamplib.tempdata\the\currentgrouplevel=luamplib.protecttextextVerbatim([===[\detokenize{#1}]===])}%
- \directlua{luamplib.processwithTEXboxes(luamplib.tempdata\the\currentgrouplevel)}%
- \else
- \edef\mplibtemp{\directlua{luamplib.protecttextext([===[\unexpanded{#1}]===])}}%
- \directlua{ tex.sprint(luamplib.mpxcolors[\the\currentgrouplevel]) }%
- \directlua{luamplib.tempdata\the\currentgrouplevel=luamplib.makeTEXboxes([===[\mplibtemp]===])}%
- \directlua{luamplib.processwithTEXboxes(luamplib.tempdata\the\currentgrouplevel)}%
- \fi
+ \directlua{luamplib.process_mplibcode([===[\unexpanded{#1}]===])}%
\endgroup
\ifnum\mplibstartlineno<\inputlineno\expandafter\mplibreplacenewlinecs\fi
}
@@ -95,16 +90,9 @@
\long\def\ltxdomplibcodeindeed#1\end#2{%
\endgroup
\toks@\expandafter{\the\toks@#1}%
- \def\mplibtemp@a{#2}\ifx\mplib@mplibcode\mplibtemp@a
- \ifdefined\mplibverbatimYes
- \directlua{luamplib.tempdata\the\currentgrouplevel=luamplib.protecttextextVerbatim([===[\the\toks@]===])}%
- \directlua{luamplib.processwithTEXboxes(luamplib.tempdata\the\currentgrouplevel)}%
- \else
- \edef\mplibtemp{\directlua{luamplib.protecttextext([===[\the\toks@]===])}}%
- \directlua{ tex.sprint(luamplib.mpxcolors[\the\currentgrouplevel]) }%
- \directlua{luamplib.tempdata\the\currentgrouplevel=luamplib.makeTEXboxes([===[\mplibtemp]===])}%
- \directlua{luamplib.processwithTEXboxes(luamplib.tempdata\the\currentgrouplevel)}%
- \fi
+ \def\mplibtemp@a{#2}%
+ \ifx\mplib@mplibcode\mplibtemp@a
+ \directlua{luamplib.process_mplibcode([===[\the\toks@]===])}%
\end{mplibcode}%
\ifnum\mplibstartlineno<\inputlineno
\expandafter\expandafter\expandafter\mplibreplacenewlinebr
@@ -114,16 +102,23 @@
\fi
}
\fi
-\def\mplibverbatim#1{%
- \begingroup
- \def\mplibtempa{#1}\def\mplibtempb{enable}%
- \expandafter\endgroup
- \ifx\mplibtempa\mplibtempb
- \let\mplibverbatimYes\relax
- \else
- \let\mplibverbatimYes\undefined
- \fi
-}
+\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
+}}
+\newtoks\mplibtmptoks
\newtoks\everymplibtoks
\newtoks\everyendmplibtoks
\protected\def\everymplib{%
@@ -149,11 +144,11 @@
\ifnum\mplibstartlineno<\inputlineno\expandafter\mplibreplacenewlinebr\fi
}
\def\mpdim#1{ begingroup \the\dimexpr #1\relax\space endgroup } % gmp.sty
-\def\mplibcolor#1{%
- \def\set@color{\edef#1{1 withprescript "MPlibOverrideColor=\current@color"}}%
- \color
-}
-\def\mplibnumbersystem#1{\directlua{luamplib.numbersystem = "#1"}}
+\def\mplibnumbersystem#1{\directlua{
+ local t = "#1"
+ if t == "binary" then t = "decimal" end
+ luamplib.numbersystem = t
+}}
\def\mplibmakenocache#1{\mplibdomakenocache #1,*,}
\def\mplibdomakenocache#1,{%
\ifx\empty#1\empty
@@ -177,36 +172,30 @@
\fi
}
\def\mplibcachedir#1{\directlua{luamplib.getcachedir("\unexpanded{#1}")}}
-\def\mplibtextextlabel#1{%
- \begingroup
- \def\tempa{enable}\def\tempb{#1}%
- \ifx\tempa\tempb
- \directlua{luamplib.textextlabel = true}%
- \else
- \directlua{luamplib.textextlabel = false}%
- \fi
- \endgroup
-}
-\def\mplibcodeinherit#1{%
- \begingroup
- \def\tempa{enable}\def\tempb{#1}%
- \ifx\tempa\tempb
- \directlua{luamplib.codeinherit = true}%
- \else
- \directlua{luamplib.codeinherit = false}%
- \fi
- \endgroup
-}
-\def\mplibglobaltextext#1{%
- \begingroup
- \def\tempa{enable}\def\tempb{#1}%
- \ifx\tempa\tempb
- \directlua{luamplib.globaltextext = true}%
- \else
- \directlua{luamplib.globaltextext = false}%
- \fi
- \endgroup
-}
+\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
+}}
\ifx\mplibscratchbox\undefined \newbox\mplibscratchbox \fi
\def\mplibstarttoPDF#1#2#3#4{%
\hbox\bgroup