summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/luatex/luamplib/luamplib.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/source/luatex/luamplib/luamplib.dtx')
-rw-r--r--Master/texmf-dist/source/luatex/luamplib/luamplib.dtx542
1 files changed, 399 insertions, 143 deletions
diff --git a/Master/texmf-dist/source/luatex/luamplib/luamplib.dtx b/Master/texmf-dist/source/luatex/luamplib/luamplib.dtx
index edae80ada69..f40d1add132 100644
--- a/Master/texmf-dist/source/luatex/luamplib/luamplib.dtx
+++ b/Master/texmf-dist/source/luatex/luamplib/luamplib.dtx
@@ -85,7 +85,7 @@ See source file '\inFileName' for licencing and contact information.
%<*driver>
\NeedsTeXFormat{LaTeX2e}
\ProvidesFile{luamplib.drv}%
- [2024/06/14 v2.32.2 Interface for using the mplib library]%
+ [2024/07/08 v2.33.0 Interface for using the mplib library]%
\documentclass{ltxdoc}
\usepackage{metalogo,multicol,mdwlist,fancyvrb,xspace}
\usepackage[x11names]{xcolor}
@@ -153,7 +153,7 @@ 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{2024/06/14 v2.32.2}
+% \date{2024/07/08 v2.33.0}
%
% \maketitle
%
@@ -431,7 +431,7 @@ See source file '\inFileName' for licencing and contact information.
% |\mplibshowlog{disable}| will revert this functionality.
% This is a \TeX{} side interface for |luamplib.showlog|. (v2.20.8)
%
-% \paragraph{Settings regarding cache files}
+% \paragraph{About 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.
@@ -562,7 +562,8 @@ See source file '\inFileName' for licencing and contact information.
% \endmppattern % or \end{mppattern}
%
% \mpfig
-% fill fullcircle scaled 100 withpostscript "collect";
+% fill fullcircle scaled 100
+% withpostscript "collect" ;
% draw unitsquare shifted - center unitsquare scaled 45
% withpattern "mypatt"
% withpostscript "evenodd" ;
@@ -576,10 +577,10 @@ See source file '\inFileName' for licencing and contact information.
% |ystep| &\textit{number} & vertical spacing between pattern cells\\
% |xshift| &\textit{number} & horizontal shifting of pattern cells\\
% |yshift| &\textit{number} & vertical shifting of pattern cells\\
-% |matrix| &\textit{table} or \textit{string} & |xx|, |yx|, |xy|, |yy| values\kern1pt* or MP transformation code\\
+% |matrix| &\textit{table} or \textit{string} & |xx|, |yx|, |xy|, |yy| values\kern1pt* or MP transform code\\
% |bbox| &\textit{table} or \textit{string} & |llx|, |lly|, |urx|, |ury| values\kern1pt*\\
% |resources|&\textit{string} & PDF resources if needed\\
-% |colored| &\textit{boolean}& |false| for uncolored pattern. default: |true|\\\hline
+% |colored| or |coloured| &\textit{boolean}& |false| for uncolored pattern. default: |true|\\\hline
% & & \small *\,in string type, numbers are separated by spaces\\
% \end{tabular}
% \end{center}
@@ -597,39 +598,111 @@ See source file '\inFileName' for licencing and contact information.
% However, as luamplib automatically includes the resources of the current page, this option
% is not needed in most cases.
%
-% Option |colored=false| will generate an uncolored pattern which shall have no color at all.
+% Option |colored=false| (|coloured| is a synonym of |colored|) will generate an uncolored pattern which shall have no color at all.
% Uncolored pattern will be painted later by the color of a metapost object.
% An example:
% \begin{verbatim}
% \begin{mppattern}{pattuncolored}
% [
% colored = false,
-% matrix = "rotated 30",
+% matrix = "slanted .3 rotated 30",
% ]
% \tiny\TeX
% \end{mppattern}
%
% \begin{mplibcode}
% beginfig(1)
-% picture tex; tex := mpliboutlinetext.p ("\bfseries \TeX");
-% i:=0;
-% for item within tex:
-% i:=i+1;
-% if i < length tex:
-% fill pathpart item scaled 10
-% withpostscript "collect";
-% else:
+% picture tex;
+% tex = mpliboutlinetext.p ("\bfseries \TeX");
+% for i=1 upto mpliboutlinenum:
+% j:=0;
+% for item within mpliboutlinepic[i]:
+% j:=j+1;
% draw pathpart item scaled 10
-% withpattern "pattuncolored"
-% withpen pencircle scaled 0.5
-% withcolor 0.7 blue % paints the pattern
-% ;
-% fi
+% if j < length mpliboutlinepic[i]:
+% withpostscript "collect"
+% else:
+% withpattern "pattuncolored"
+% withpen pencircle scaled 1/2
+% withcolor (i/4)[red,blue] % paints the pattern
+% fi;
+% endfor
% endfor
% endfig;
% \end{mplibcode}
% \end{verbatim}
%
+% \paragraph{\texttt{withfademethod} and related macros}
+% |withfademethod| is a metapost operator which makes the color of an object gradiently transparent.
+% The syntax is \textit{<path>}\texttt{\char"7C}\textit{<picture>} |withfademethod| \textit{<string>},
+% the latter being either |"linear"| or |"circular"|.
+% Though it is similar to the |withshademethod| provided by metafun,
+% the differences are: (1) the operand of |withfademethod| can be a picture as well as a path;
+% (2) you cannot make gradient colors, but can only make gradient opacity.
+%
+% Related macros to control optional values are:
+% \begin{description}
+% \item [|withfadeopacity (|\textit{\mdseries number, number}|)|]
+% sets the starting opacity and the ending opacity, default value being |(1,0)|.
+% `|1|' denotes full color; `|0|' full transparency.
+% \item [|withfadevector (|\textit{\mdseries pair, pair}|)|]
+% sets the starting and ending points. Default value in the linear mode is
+% |(llcorner p, lrcorner p)|, where |p| is the operand,
+% meaning that fading starts from the left edge and ends at the right edge.
+% Default value in the circular mode is |(center p, center p)|, which means
+% centers of both starting and ending circles are the center of the bounding box.
+% \item [|withfadecenter|] is a synonym of |withfadevector|.
+% \item [|withfaderadius (|\textit{\mdseries number, number}|)|]
+% sets the radii of starting and ending circles. This is no-op in the linear mode.
+% Default value is |(0, abs(center p - urcorner p))|, meaning that fading starts from the
+% center and ends at the four corners of the bounding box.
+% \item [|withfadebbox (|\textit{\mdseries pair, pair}|)|]
+% sets the bounding box of the fading area, default value being |(llcorner p, urcorner p)|.
+% Though this option is not needed in most cases, there could be cases when users want to
+% explicitly control the bounding box.
+% \end{description}
+% An example:
+% \begin{verbatim}
+% \mpfig
+% picture mill;
+% mill = btex \includegraphics[width=100bp]{mill} etex;
+% draw mill
+% withfademethod "circular"
+% withfadecenter (center mill, center mill)
+% withfaderadius (20, 50)
+% withfadeopacity (1, 0)
+% ;
+% \endmpfig
+% \end{verbatim}
+%
+% \paragraph{Lua table \texttt{luamplib.instances}}
+% Users can access the Lua table containing mplib instances, |luamplib.instances|,
+% through which metapost variables are also easily accessible
+% as documented in Lua\TeX{} manual \textsection\,11.2.8.4 (|texdoc luatex|).
+% The following will print |false|, |3.0|, |MetaPost| and
+% the points and the cyclicity of the path |unitsquare|, consecutively.
+% \begin{verbatim}
+% \begin{mplibcode}[instance1]
+% boolean b; b = 1 > 2;
+% numeric n; n = 3;
+% string s; s = "MetaPost";
+% path p; p = unitsquare;
+% \end{mplibcode}
+%
+% \directlua{
+% local instance1 = luamplib.instances.instance1
+% print( instance1:get_boolean"b" )
+% print( instance1:get_number"n" )
+% print( instance1:get_string"s" )
+% local t = instance1:get_path"p"
+% for k,v in pairs(t) do
+% print(k, type(v)=='table' and table.concat(v,' ') or v)
+% end
+% }
+% \end{verbatim}
+% In this way, it would not be difficult to define a paragraph shape
+% (using \cs{parshape} \TeX\ primitive) which follows an arbitrary metapost path.
+%
% \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.
@@ -662,8 +735,8 @@ See source file '\inFileName' for licencing and contact information.
luatexbase.provides_module {
name = "luamplib",
- version = "2.32.2",
- date = "2024/06/14",
+ version = "2.33.0",
+ date = "2024/07/08",
description = "Lua package to typeset Metapost with LuaTeX's MPLib.",
}
@@ -725,6 +798,7 @@ luamplib.showlog = luamplib.showlog or false
% \begin{macrocode}
local tableconcat = table.concat
local tableinsert = table.insert
+local tableunpack = table.unpack
local texsprint = tex.sprint
local texgettoks = tex.gettoks
local texgetbox = tex.getbox
@@ -1004,6 +1078,7 @@ end
% \begin{macrocode}
luamplib.codeinherit = false
local mplibinstances = {}
+luamplib.instances = mplibinstances
local has_instancename = false
local function reporterror (result, prevlog)
@@ -1047,6 +1122,12 @@ local function reporterror (result, prevlog)
end
end
+% \end{macrocode}
+%
+% |lualibs-os.lua| installs a randomseed. When this file is not loaded,
+% we should explicitly seed a unique interger to get random randomseed for each run.
+% \begin{macrocode}
+if not math.initialseed then math.randomseed(currenttime) end
local function luamplibload (name)
local mpx = mplib.new {
ini_version = true,
@@ -1200,8 +1281,7 @@ local function process_tex_text (str)
else
local boxid = texboxes.globalid + 1
texboxes.globalid = boxid
- run_tex_code(format(
- [[\expandafter\newbox\csname luamplib.box.%s\endcsname]], boxid))
+ run_tex_code(format([[\expandafter\newbox\csname luamplib.box.%s\endcsname]], boxid))
tex_box_id = tex.getcount'allocationnumber'
end
run_tex_code(format("%s\\setbox%i\\hbox{%s}", global, tex_box_id, str))
@@ -1408,7 +1488,7 @@ function luamplib.runscript (code)
return buffer
end
buffer = {}
- mpprint(buffer, table.unpack(res))
+ mpprint(buffer, tableunpack(res))
return tableconcat(buffer)
end
return ""
@@ -1542,27 +1622,48 @@ luamplib.shadecolor = function (str)
% \end{mplibcode}
% \end{document}
% \end{verbatim}
+% another one: user-defined DeviceN colorspace
+% \begin{verbatim}
+% \DocumentMetadata{ }
+% \documentclass{article}
+% \usepackage{luamplib}
+% \mplibsetformat{metafun}
+% \ExplSyntaxOn
+% \color_model_new:nnn { pantone1215 }
+% { Separation }
+% { name = PANTONE~1215~U ,
+% alternative-model = cmyk ,
+% alternative-values = {0, 0.15, 0.51, 0}
+% }
+% \color_model_new:nnn { pantone+black }
+% { DeviceN }
+% {
+% names = {pantone1215,black}
+% }
+% \color_set:nnn{purepantone}{pantone+black}{1,0}
+% \color_set:nnn{pureblack} {pantone+black}{0,1}
+% \ExplSyntaxOff
+% \begin{document}
+% \mpfig
+% fill unitsquare xscaled \mpdim{\textwidth} yscaled 30
+% withshademethod "linear"
+% withshadecolors ("purepantone","pureblack")
+% ;
+% \endmpfig
+% \end{document}
+% \end{verbatim}
% \begin{macrocode}
run_tex_code({
[[\color_export:nnN{]], str, [[}{backend}\mplib_@tempa]],
},ccexplat)
- local name = get_macro'mplib_@tempa':match'{(.-)}{.+}'
+ local name, value = get_macro'mplib_@tempa':match'{(.-)}{(.-)}'
local t, obj = res:explode()
if pdfmode then
- obj = t[1]:match"^/(.+)"
- if ltx.pdf and ltx.pdf.object_id then
- obj = format("%s 0 R", ltx.pdf.object_id(obj))
- else
- run_tex_code({
- [[\edef\mplib_@tempa{\pdf_object_ref:n{]], obj, "}}",
- },ccexplat)
- obj = get_macro'mplib_@tempa'
- end
+ obj = format("%s 0 R", ltx.pdf.object_id( t[1]:sub(2,-1) ))
else
obj = t[2]
end
- local value = t[3]:match"%[(.-)%]" or t[3]
- return format('(%s) withprescript"mplib_spotcolor=%s:%s"', value,obj,name)
+ return format('(1) withprescript"mplib_spotcolor=%s:%s:%s"', value,obj,name)
end
return colorsplit(res)
end
@@ -1868,7 +1969,7 @@ function luamplib.glyph (f, c)
if not gid then return mperr"cannot get GID (glyph id)" end
local fac = 1000 / (shapedata.units or 1000)
local t = shapedata.glyphs[gid].segments
- if not t then return "image(fill fullcircle scaled 0;)" end
+ if not t then return "image()" end
for i,v in ipairs(t) do
if type(v) == "table" then
for ii,vv in ipairs(v) do
@@ -2122,7 +2223,7 @@ function luamplib.outlinetext (text)
local id = tonumber(fmt:match"mplibtexboxid=(%d+):")
local box = texgetbox(id)
local res = outline_horz({ }, box, box.head, 0, 0)
- if #res == 0 then res = { "mpliboutlinepic[1]:=image(fill fullcircle scaled 0;);" } end
+ if #res == 0 then res = { "mpliboutlinepic[1]:=image();" } end
return tableconcat(res) .. format("mpliboutlinenum:=%i;", #res)
end
@@ -2327,6 +2428,39 @@ vardef mplibtransformmatrix (text e) =
& decimal ypart t & ","
& "}");
enddef;
+primarydef p withfademethod s =
+ p withprescript "mplibfadetype=" & s
+ withprescript "mplibfadebbox=" &
+ decimal xpart llcorner p & ":" &
+ decimal ypart llcorner p & ":" &
+ decimal xpart urcorner p & ":" &
+ decimal ypart urcorner p
+enddef;
+def withfadeopacity (expr a,b) =
+ withprescript "mplibfadeopacity=" &
+ decimal a & ":" &
+ decimal b
+enddef;
+def withfadevector (expr a,b) =
+ withprescript "mplibfadevector=" &
+ decimal xpart a & ":" &
+ decimal ypart a & ":" &
+ decimal xpart b & ":" &
+ decimal ypart b
+enddef;
+let withfadecenter = withfadevector;
+def withfaderadius (expr a,b) =
+ withprescript "mplibfaderadius=" &
+ decimal a & ":" &
+ decimal b
+enddef;
+def withfadebbox (expr a,b) =
+ withprescript "mplibfadebbox=" &
+ decimal xpart a & ":" &
+ decimal ypart a & ":" &
+ decimal xpart b & ":" &
+ decimal ypart b
+enddef;
]],
legacyverbatimtex = [[
def specialVerbatimTeX (text t) = runscript("luamplibprefig{"&t&"}") enddef;
@@ -2680,31 +2814,42 @@ pdfetcs.pgfextgs = "pgf@sys@addpdfresource@extgs@plain"
pdfetcs.pgfpattern = "pgf@sys@addpdfresource@patterns@plain"
pdfetcs.pgfcolorspace = "pgf@sys@addpdfresource@colorspaces@plain"
-local function update_pdfobjs (os)
- local on = pdfobjs[os]
+local function update_pdfobjs (os, stream)
+ local key = os
+ if stream then key = key..stream end
+ local on = pdfobjs[key]
if on then
return on,false
end
if pdfmode then
- on = pdf.immediateobj(os)
+ if stream then
+ on = pdf.immediateobj("stream",stream,os)
+ else
+ on = pdf.immediateobj(os)
+ end
else
on = pdfetcs.cnt or 1
- texsprint(format("\\special{pdf:obj @mplibpdfobj%s %s}",on,os))
+ if stream then
+ texsprint(format("\\special{pdf:stream @mplibpdfobj%s (%s) <<%s>>}",on,stream,os))
+ else
+ texsprint(format("\\special{pdf:obj @mplibpdfobj%s %s}",on,os))
+ end
pdfetcs.cnt = on + 1
end
- pdfobjs[os] = on
+ pdfobjs[key] = on
return on,true
end
if pdfmode then
pdfetcs.getpageres = pdf.getpageresources or function() return pdf.pageresources end
- pdfetcs.setpageres = pdf.setpageresources or function(s) pdf.pageresources = s end
- pdfetcs.initialize_resources = function (name)
+ local getpageres = pdfetcs.getpageres
+ local setpageres = pdf.setpageresources or function(s) pdf.pageresources = s end
+ local initialize_resources = function (name)
local tabname = format("%s_res",name)
pdfetcs[tabname] = { }
if luatexbase.callbacktypes.finish_pdffile then -- ltluatex
local obj = pdf.reserveobj()
- pdfetcs.setpageres(format("%s/%s %i 0 R", pdfetcs.getpageres() or "", name, obj))
+ setpageres(format("%s/%s %i 0 R", getpageres() or "", name, obj))
luatexbase.add_to_callback("finish_pdffile", function()
pdf.immediateobj(obj, format("<<%s>>", tableconcat(pdfetcs[tabname])))
end,
@@ -2712,21 +2857,29 @@ if pdfmode then
end
end
pdfetcs.fallback_update_resources = function (name, res)
+ local tabname = format("%s_res",name)
+ if not pdfetcs[tabname] then
+ initialize_resources(name)
+ end
if luatexbase.callbacktypes.finish_pdffile then
- local t = pdfetcs[format("%s_res",name)]
+ local t = pdfetcs[tabname]
t[#t+1] = res
else
- local tpr, n = pdfetcs.getpageres() or "", 0
+ local tpr, n = getpageres() or "", 0
tpr, n = tpr:gsub(format("/%s<<",name), "%1"..res)
if n == 0 then
tpr = format("%s/%s<<%s>>", tpr, name, res)
end
- pdfetcs.setpageres(tpr)
+ setpageres(tpr)
end
end
else
- texsprint("\\special{pdf:obj @MPlibTr<<>>}","\\special{pdf:obj @MPlibSh<<>>}",
- "\\special{pdf:obj @MPlibCS<<>>}","\\special{pdf:obj @MPlibPt<<>>}")
+ texsprint {
+ "\\special{pdf:obj @MPlibTr<<>>}",
+ "\\special{pdf:obj @MPlibSh<<>>}",
+ "\\special{pdf:obj @MPlibCS<<>>}",
+ "\\special{pdf:obj @MPlibPt<<>>}",
+ }
end
% \end{macrocode}
@@ -2740,57 +2893,56 @@ local transparancy_modes = { [0] = "Normal",
"Hue", "Saturation", "Color", "Luminosity",
"Compatible",
}
-
-local function update_tr_res(mode,opaq)
- local os = format("<</BM /%s/ca %.3f/CA %.3f/AIS false>>",mode,opaq,opaq)
- local on, new = update_pdfobjs(os)
- if not new then return on end
+local function add_extgs_resources (on, new)
local key = format("MPlibTr%s", on)
- local val = format(pdfmode and "%s 0 R" or "@mplibpdfobj%s", on)
- if pdfmanagement then
- texsprint(ccexplat,
- format("\\pdfmanagement_add:nnn{Page/Resources/ExtGState}{%s}{%s}", key, val))
- else
- local tr = format("/%s %s", key, val)
- if is_defined(pdfetcs.pgfextgs) then
- texsprint(format("\\csname %s\\endcsname{%s}", pdfetcs.pgfextgs,tr))
- elseif pdfmode then
- if is_defined"TRP@list" then
- texsprint(catat11,{
- [[\if@filesw\immediate\write\@auxout{]],
- [[\string\g@addto@macro\string\TRP@list{]],
- tr,
- [[}}\fi]],
- })
- if not get_macro"TRP@list":find(tr) then
- texsprint(catat11,[[\global\TRP@reruntrue]])
+ if new then
+ local val = format(pdfmode and "%s 0 R" or "@mplibpdfobj%s", on)
+ if pdfmanagement then
+ texsprint {
+ "\\csname pdfmanagement_add:nnn\\endcsname{Page/Resources/ExtGState}{", key, "}{", val, "}"
+ }
+ else
+ local tr = format("/%s %s", key, val)
+ if is_defined(pdfetcs.pgfextgs) then
+ texsprint { "\\csname ", pdfetcs.pgfextgs, "\\endcsname{", tr, "}" }
+ elseif pdfmode then
+ if is_defined"TRP@list" then
+ texsprint(catat11,{
+ [[\if@filesw\immediate\write\@auxout{]],
+ [[\string\g@addto@macro\string\TRP@list{]],
+ tr,
+ [[}}\fi]],
+ })
+ if not get_macro"TRP@list":find(tr) then
+ texsprint(catat11,[[\global\TRP@reruntrue]])
+ end
+ else
+ pdfetcs.fallback_update_resources("ExtGState", tr)
end
else
- if not pdfetcs.ExtGState_res then
- pdfetcs.initialize_resources"ExtGState"
- end
- pdfetcs.fallback_update_resources("ExtGState", tr)
+ texsprint { "\\special{pdf:put @MPlibTr<<", tr, ">>}" }
end
- else
- texsprint(format("\\special{pdf:put @MPlibTr<<%s>>}",tr))
- texsprint"\\special{pdf:put @resources<</ExtGState @MPlibTr>>}"
end
end
- return on
+ if not pdfmode and not pdfmanagement and not is_defined(pdfetcs.pgfextgs) then
+ texsprint"\\special{pdf:put @resources <</ExtGState @MPlibTr>>}"
+ end
+ return key
end
-
local function do_preobj_TR(object,prescript)
if object.postscript == "collect" then return end
local opaq = prescript and prescript.tr_transparency
- local tron_no
+ local on
if opaq then
local mode = prescript.tr_alternative or 1
mode = transparancy_modes[tonumber(mode)]
- tron_no = update_tr_res(mode, opaq)
+ local os, new = format("<</BM /%s/ca %.3f/CA %.3f/AIS false>>",mode,opaq,opaq)
+ on, new = update_pdfobjs(os)
+ local key = add_extgs_resources(on,new)
start_pdf_code()
- pdf_literalcode("/MPlibTr%i gs",tron_no)
+ pdf_literalcode("/%s gs",key)
end
- return tron_no
+ return on
end
% \end{macrocode}
@@ -2829,24 +2981,25 @@ local function sh_pdfpageresources(shtype,domain,colorspace,ca,cb,coordinates,st
"/Extend [true true]/AntiAlias true>>",
}
local on, new = update_pdfobjs(os)
- if not new then return on end
- local key = format("MPlibSh%s", on)
- local val = format(pdfmode and "%s 0 R" or "@mplibpdfobj%s", on)
- if pdfmanagement then
- texsprint(ccexplat,
- format("\\pdfmanagement_add:nnn{Page/Resources/Shading}{%s}{%s}", key, val))
- else
- local res = format("/%s %s", key, val)
- if pdfmode then
- if not pdfetcs.Shading_res then
- pdfetcs.initialize_resources"Shading"
- end
- pdfetcs.fallback_update_resources("Shading", res)
+ if new then
+ local key = format("MPlibSh%s", on)
+ local val = format(pdfmode and "%s 0 R" or "@mplibpdfobj%s", on)
+ if pdfmanagement then
+ texsprint {
+ "\\csname pdfmanagement_add:nnn\\endcsname{Page/Resources/Shading}{", key, "}{", val, "}"
+ }
else
- texsprint(format("\\special{pdf:put @MPlibSh<<%s>>}", res))
- texsprint"\\special{pdf:put @resources<</Shading @MPlibSh>>}"
+ local res = format("/%s %s", key, val)
+ if pdfmode then
+ pdfetcs.fallback_update_resources("Shading", res)
+ else
+ texsprint { "\\special{pdf:put @MPlibSh<<", res, ">>}" }
+ end
end
end
+ if not pdfmode and not pdfmanagement then
+ texsprint"\\special{pdf:put @resources <</Shading @MPlibSh>>}"
+ end
return on
end
@@ -2927,15 +3080,14 @@ local function do_preobj_SH(object,prescript)
local script = object.prescript:explode"\13+"
for i=#script,1,-1 do
if script[i]:find"mplib_spotcolor" then
- local name, value
- objref, name = script[i]:match"=(.-):(.+)"
- value = script[i+1]:match"=(.+)"
+ local t, name, value = script[i]:explode"="[2]:explode":"
+ value, objref, name = t[1], t[2], t[3]
if not names[name] then
pos = pos+1
names[name] = pos
names[#names+1] = name
end
- local t = { }
+ t = { }
for j=1,names[name] do t[#t+1] = 0 end
t[#t+1] = value
tableinsert(#ca == #cb and ca or cb, t)
@@ -2995,7 +3147,8 @@ end
%
% Patterns
% \begin{macrocode}
-patterns = { }
+pdfetcs.patterns = { }
+local patterns = pdfetcs.patterns
function luamplib.registerpattern ( boxid, name, opts )
local box = texgetbox(boxid)
local wd = format("%.3f",box.width/factor)
@@ -3003,7 +3156,12 @@ function luamplib.registerpattern ( boxid, name, opts )
info("w/h/d of '%s': %s %s 0.0", name, wd, hd)
if opts.xstep == 0 then opts.xstep = nil end
if opts.ystep == 0 then opts.ystep = nil end
- if opts.colored == nil then opts.colored = true end
+ if opts.colored == nil then
+ opts.colored = opts.coloured
+ if opts.colored == nil then
+ opts.colored = true
+ end
+ end
if type(opts.matrix) == "table" then opts.matrix = tableconcat(opts.matrix," ") end
if type(opts.bbox) == "table" then opts.bbox = tableconcat(opts.bbox," ") end
if opts.matrix and opts.matrix:find"%a" then
@@ -3029,7 +3187,7 @@ function luamplib.registerpattern ( boxid, name, opts )
for _,v in ipairs{"ExtGState","ColorSpace","Shading"} do
local pp = get_macro(format("g__pdfdict_/g__pdf_Core/Page/Resources/%s_prop",v))
if pp and pp:find"__prop_pair" then
- t[#t+1] = format("/%s %s", v, ltx.__pdf.object["__pdf/Page/Resources/"..v])
+ t[#t+1] = format("/%s %s 0 R", v, ltx.pdf.object_id("__pdf/Page/Resources/"..v))
end
end
else
@@ -3055,17 +3213,24 @@ function luamplib.registerpattern ( boxid, name, opts )
local optres, t = opts.resources or "", { }
if pdfmanagement then
for _,v in ipairs{"ExtGState","ColorSpace","Shading"} do
- run_tex_code(format(
- [[\mplibtmptoks\expanded{{/%s \pdf_object_ref:n{__pdf/Page/Resources/%s}}}]],v,v),ccexplat)
- t[#t+1] = texgettoks'mplibtmptoks'
+ local pp = get_macro(format("g__pdfdict_/g__pdf_Core/Page/Resources/%s_prop",v))
+ if pp and pp:find"__prop_pair" then
+ run_tex_code {
+ "\\mplibtmptoks\\expanded{{",
+ format("/%s \\csname pdf_object_ref:n\\endcsname{__pdf/Page/Resources/%s}",v,v),
+ "}}",
+ }
+ t[#t+1] = texgettoks'mplibtmptoks'
+ end
end
elseif is_defined(pdfetcs.pgfextgs) then
- run_tex_code("\\mplibtmptoks\\expanded{{\z
- \\ifpgf@sys@pdf@extgs@exists /ExtGState @pgfextgs\\fi\z
- \\ifpgf@sys@pdf@colorspaces@exists /ColorSpace @pgfcolorspaces\\fi}}",catat11)
+ run_tex_code ({
+ "\\mplibtmptoks\\expanded{{",
+ "\\ifpgf@sys@pdf@extgs@exists /ExtGState @pgfextgs\\fi",
+ "\\ifpgf@sys@pdf@colorspaces@exists /ColorSpace @pgfcolorspaces\\fi",
+ "}}",
+ }, catat11)
t[#t+1] = texgettoks'mplibtmptoks'
- else
- t[#t+1] = "/ExtGState @MPlibTr/Shading @MPlibSh/ColorSpace @MPlibCS"
end
optres = optres .. tableconcat(t)
texsprint {
@@ -3089,22 +3254,23 @@ local function pattern_colorspace (cs)
local key = format("MPlibCS%i",on)
local val = pdfmode and format("%i 0 R",on) or format("@mplibpdfobj%i",on)
if pdfmanagement then
- texsprint(ccexplat,format("\\pdfmanagement_add:nnn{Page/Resources/ColorSpace}{%s}{%s}",key,val))
+ texsprint {
+ "\\csname pdfmanagement_add:nnn\\endcsname{Page/Resources/ColorSpace}{", key, "}{", val, "}"
+ }
else
local res = format("/%s %s", key, val)
if is_defined(pdfetcs.pgfcolorspace) then
- texsprint(format("\\csname %s\\endcsname{%s}", pdfetcs.pgfcolorspace, res))
+ texsprint { "\\csname ", pdfetcs.pgfcolorspace, "\\endcsname{", res, "}" }
elseif pdfmode then
- if not pdfetcs.ColorSpace_res then
- pdfetcs.initialize_resources"ColorSpace"
- end
pdfetcs.fallback_update_resources("ColorSpace", res)
else
- texsprint(format("\\special{pdf:put @MPlibCS<<%s>>}", res))
- texsprint"\\special{pdf:put @resources<</ColorSpace @MPlibCS>>}"
+ texsprint { "\\special{pdf:put @MPlibCS<<", res, ">>}" }
end
end
end
+ if not pdfmode and not pdfmanagement and not is_defined(pdfetcs.pgfcolorspace) then
+ texsprint"\\special{pdf:put @resources <</ColorSpace @MPlibCS>>}"
+ end
return on
end
local function do_preobj_PAT(object, prescript)
@@ -3139,29 +3305,115 @@ local function do_preobj_PAT(object, prescript)
end
pdf_literalcode("/MPlibCS%i cs %s /%s scn", pattern_colorspace(cs), color, key)
end
- if patt.done then return end
- local val = pdfmode and format("%s 0 R",index) or patterns[index]
- if pdfmanagement then
- texsprint(ccexplat, format("\\pdfmanagement_add:nnn{Page/Resources/Pattern}{%s}{%s}",key,val))
- else
- local res = format("/%s %s", key, val)
- if is_defined(pdfetcs.pgfpattern) then
- texsprint(format("\\csname %s\\endcsname{%s}", pdfetcs.pgfpattern, res))
- elseif pdfmode then
- if not pdfetcs.Pattern_res then
- pdfetcs.initialize_resources"Pattern"
- end
- pdfetcs.fallback_update_resources("Pattern", res)
+ if not patt.done then
+ local val = pdfmode and format("%s 0 R",index) or patterns[index]
+ if pdfmanagement then
+ texsprint {
+ "\\csname pdfmanagement_add:nnn\\endcsname{Page/Resources/Pattern}{", key, "}{", val, "}"
+ }
else
- texsprint(format("\\special{pdf:put @MPlibPt<<%s>>}", res))
- texsprint"\\special{pdf:put @resources<</Pattern @MPlibPt>>}"
+ local res = format("/%s %s", key, val)
+ if is_defined(pdfetcs.pgfpattern) then
+ texsprint { "\\csname ", pdfetcs.pgfpattern, "\\endcsname{", res, "}" }
+ elseif pdfmode then
+ pdfetcs.fallback_update_resources("Pattern", res)
+ else
+ texsprint { "\\special{pdf:put @MPlibPt<<", res, ">>}" }
+ end
end
end
+ if not pdfmode and not pdfmanagement and not is_defined(pdfetcs.pgfpattern) then
+ texsprint"\\special{pdf:put @resources <</Pattern @MPlibPt>>}"
+ end
patt.done = true
end
% \end{macrocode}
%
+% Fading
+% \begin{macrocode}
+local function do_preobj_FADE (object, prescript)
+ if object.postscript == "collect" then return end
+ local fd_type = prescript and prescript.mplibfadetype
+ if not fd_type then return end
+ local dx, dy = 0, 0
+ local bbox = prescript.mplibfadebbox:explode":"
+ if tonumber(bbox[1]) < 0 then
+ dx = -bbox[1]
+ bbox[1], bbox[3] = 0, bbox[3] + dx
+ end
+ if tonumber(bbox[2]) < 0 then
+ dy = -bbox[2]
+ bbox[2], bbox[4] = 0, bbox[4] + dy
+ end
+ local vec, coords = prescript.mplibfadevector, { }
+ if vec then
+ vec = vec:explode":"
+ for i=1,4 do
+ coords[#coords+1] = vec[i] + (i % 2 == 0 and dy or dx)
+ end
+ end
+ if fd_type == "linear" then
+ if not vec then
+ coords = { bbox[1], bbox[2], bbox[3], bbox[2] } -- left to right
+ end
+ coords = format("%f %f %f %f", tableunpack(coords))
+ elseif fd_type == "circular" then
+ local width, height = bbox[3]-bbox[1], bbox[4]-bbox[2]
+ if not vec then
+ coords = { width/2, height/2, width/2, height/2 } -- center for both circle
+ end
+ local radius = prescript.mplibfaderadius or format("0:%f",math.sqrt(width^2+height^2)/2);
+ radius = radius:explode":"
+ tableinsert(coords, 3, radius[1])
+ tableinsert(coords, radius[2])
+ coords = format("%f %f %f %f %f %f", tableunpack(coords))
+ else
+ err("unknown fading method '%s'", fd_type)
+ end
+ fd_type = fd_type == "linear" and 2 or 3
+ bbox = format("%f %f %f %f", tableunpack(bbox))
+ local opaq = (prescript.mplibfadeopacity or "1:0"):explode":"
+ local ca, cb = {{ opaq[1] }}, {{ opaq[2] }}
+ local on, os, new
+ on = sh_pdfpageresources(fd_type, "0 1", "/DeviceGray", ca, cb, coords, 1)
+ if pdfmode then
+ os = format("<</PatternType 2/Shading %s 0 R>>", on)
+ else
+ os = format("<</PatternType 2/Shading @mplibpdfobj%s>>", on)
+ end
+ on = update_pdfobjs(os)
+ local streamtext = format("q /Pattern cs/MPlibFd%s scn %s re f Q", on, bbox)
+ if pdfmode then
+ os = format("<</Pattern<</MPlibFd%s %s 0 R>>>>", on, on)
+ else
+ os = format("<</Pattern<</MPlibFd%s @mplibpdfobj%s>>>>", on, on)
+ end
+ on = update_pdfobjs(os)
+ local resources = "/Resources "..format(pdfmode and "%s 0 R" or "@mplibpdfobj%s", on)
+ on = update_pdfobjs"<</S/Transparency/CS/DeviceGray>>"
+ local attr = tableconcat{
+ "/Subtype/Form",
+ format("/BBox[%s]", bbox),
+ format("/Matrix[1 0 0 1 %f %f]", -dx, -dy),
+ resources,
+ "/Group ", format(pdfmode and "%s 0 R" or "@mplibpdfobj%s", on),
+ }
+ on = update_pdfobjs(attr, streamtext)
+ os = tableconcat {
+ "<</SMask<</S/Luminosity/G ",
+ format(pdfmode and "%s 0 R" or "@mplibpdfobj%s", on),
+ ">>>>",
+ }
+ on, new = update_pdfobjs(os)
+ local key = add_extgs_resources(on,new)
+ start_pdf_code()
+ pdf_literalcode("/%s gs", key)
+ return on
+end
+
+% \end{macrocode}
+%
% Finally, flush figures by inserting PDF literals.
% \begin{macrocode}
function luamplib.flush (result,flusher)
@@ -3203,13 +3455,14 @@ function luamplib.flush (result,flusher)
local object = objects[o]
local objecttype = object.type
% \end{macrocode}
-% The following 6 lines are part of |btex...etex| patch.
+% The following 7 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 cr_over = do_preobj_CR(object,prescript) -- color
local tr_opaq = do_preobj_TR(object,prescript) -- opacity
+ local fading_ = do_preobj_FADE(object,prescript) -- fading
if prescript and prescript.mplibtexboxid then
put_tex_boxes(object,prescript)
elseif objecttype == "start_bounds" or objecttype == "stop_bounds" then --skip
@@ -3387,6 +3640,9 @@ function luamplib.flush (result,flusher)
end
end
end
+ if fading_ then -- fading
+ stop_pdf_code()
+ end
if tr_opaq then -- opacity
stop_pdf_code()
end
@@ -3450,7 +3706,7 @@ end
\else
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{luamplib}
- [2024/06/14 v2.32.2 mplib package for LuaTeX]
+ [2024/07/08 v2.33.0 mplib package for LuaTeX]
\ifx\newluafunction\@undefined
\input ltluatex
\fi