diff options
Diffstat (limited to 'macros/luatex/generic/luamplib')
-rw-r--r-- | macros/luatex/generic/luamplib/NEWS | 7 | ||||
-rw-r--r-- | macros/luatex/generic/luamplib/luamplib.dtx | 293 | ||||
-rw-r--r-- | macros/luatex/generic/luamplib/luamplib.pdf | bin | 214279 -> 222052 bytes | |||
-rw-r--r-- | macros/luatex/generic/luamplib/test-luamplib-latex.tex | 42 | ||||
-rw-r--r-- | macros/luatex/generic/luamplib/test-luamplib-plain.tex | 28 |
5 files changed, 302 insertions, 68 deletions
diff --git a/macros/luatex/generic/luamplib/NEWS b/macros/luatex/generic/luamplib/NEWS index 50e7c625a9..6d0e01f1ac 100644 --- a/macros/luatex/generic/luamplib/NEWS +++ b/macros/luatex/generic/luamplib/NEWS @@ -1,5 +1,12 @@ History of the luamplib package +2024/07/08 2.33.0 + * provide a new metapost operator 'withfademethod' and related macros, + which make the color of an object gradiently transparent. see luamplib + document for details. + + * fix spot-color shading routine to support user-defined colorspace + 2024/07/03 2.32.4 * make the variable 'patterns' local * 'math.randomseed' on plain TeX diff --git a/macros/luatex/generic/luamplib/luamplib.dtx b/macros/luatex/generic/luamplib/luamplib.dtx index c050955a39..f40d1add13 100644 --- a/macros/luatex/generic/luamplib/luamplib.dtx +++ b/macros/luatex/generic/luamplib/luamplib.dtx @@ -85,7 +85,7 @@ See source file '\inFileName' for licencing and contact information. %<*driver> \NeedsTeXFormat{LaTeX2e} \ProvidesFile{luamplib.drv}% - [2024/07/03 v2.32.4 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/07/03 v2.32.4} +% \date{2024/07/08 v2.33.0} % % \maketitle % @@ -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" ; @@ -604,32 +605,76 @@ See source file '\inFileName' for licencing and contact information. % \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 @@ -690,8 +735,8 @@ See source file '\inFileName' for licencing and contact information. luatexbase.provides_module { name = "luamplib", - version = "2.32.4", - date = "2024/07/03", + version = "2.33.0", + date = "2024/07/08", description = "Lua package to typeset Metapost with LuaTeX's MPLib.", } @@ -753,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 @@ -1442,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 "" @@ -1576,19 +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 = 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 @@ -2353,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; @@ -2706,19 +2814,29 @@ 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 @@ -2775,12 +2893,9 @@ 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) +local function add_extgs_resources (on, new) + local key = format("MPlibTr%s", on) if new then - local key = format("MPlibTr%s", on) local val = format(pdfmode and "%s 0 R" or "@mplibpdfobj%s", on) if pdfmanagement then texsprint { @@ -2812,21 +2927,22 @@ local function update_tr_res(mode,opaq) if not pdfmode and not pdfmanagement and not is_defined(pdfetcs.pgfextgs) then texsprint"\\special{pdf:put @resources <</ExtGState @MPlibTr>>}" end - return on + 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} @@ -2964,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) @@ -3215,6 +3330,90 @@ 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) @@ -3256,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 @@ -3440,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 @@ -3503,7 +3706,7 @@ end \else \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{luamplib} - [2024/07/03 v2.32.4 mplib package for LuaTeX] + [2024/07/08 v2.33.0 mplib package for LuaTeX] \ifx\newluafunction\@undefined \input ltluatex \fi diff --git a/macros/luatex/generic/luamplib/luamplib.pdf b/macros/luatex/generic/luamplib/luamplib.pdf Binary files differindex 5e8e97a778..45f099c664 100644 --- a/macros/luatex/generic/luamplib/luamplib.pdf +++ b/macros/luatex/generic/luamplib/luamplib.pdf diff --git a/macros/luatex/generic/luamplib/test-luamplib-latex.tex b/macros/luatex/generic/luamplib/test-luamplib-latex.tex index c2d8cb498b..50a5778870 100644 --- a/macros/luatex/generic/luamplib/test-luamplib-latex.tex +++ b/macros/luatex/generic/luamplib/test-luamplib-latex.tex @@ -7,7 +7,7 @@ \usepackage{fontspec} \setmainfont{latin modern roman} \usepackage{luamplib} -\usepackage{xcolor} +\usepackage{graphicx,xcolor} \everymplib{ beginfig(0); } \everyendmplib{ endfig; } \mpliblegacybehavior{true}% @@ -268,19 +268,37 @@ draw mpliboutlinetext.b ("$\displaystyle\frac{1}{1-x^2}$") \tiny\TeX \end{mppattern}\relax \mpfig - 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: - draw pathpart item scaled 10 withpattern "pattuncolored" - withpen pencircle scaled 1/2 - withcolor 0.7 blue; - fi + 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 + if j < length mpliboutlinepic[i]: + withpostscript "collect" + else: + withpattern "pattuncolored" + withfademethod "linear" + withfadebbox (10 llcorner mpliboutlinepic[i], 10 urcorner mpliboutlinepic[i]) + withpen pencircle scaled 1/2 + withcolor (i/4)[red,blue] + fi; + endfor endfor \endmpfig +\par +\mpfig + picture mill; mill = btex \includegraphics[width=100bp]{mill} etex; + draw mill; + mill := mill shifted 125right; + draw mill + withfademethod "circular" + withfadecenter (center mill, center mill) + withfaderadius (20, abs(lrcorner mill - llcorner mill)/2) + withfadeopacity (1, 0) + ; +\endmpfig \tracingcommands0 \vskip 2\baselineskip diff --git a/macros/luatex/generic/luamplib/test-luamplib-plain.tex b/macros/luatex/generic/luamplib/test-luamplib-plain.tex index c178acb31a..dde6fbfb10 100644 --- a/macros/luatex/generic/luamplib/test-luamplib-plain.tex +++ b/macros/luatex/generic/luamplib/test-luamplib-plain.tex @@ -261,17 +261,23 @@ draw mpliboutlinetext.b ("$\overbrace{x+\cdots+x}^k$") \fiverm\TeX \endmppattern \mpfig - picture tex; tex := mpliboutlinetext.p ("\bf \TeX"); - i:=0; - for item within tex: - i:=i+1; - if i < length tex: - fill pathpart item scaled 10 withpostscript "collect"; - else: - draw pathpart item scaled 10 withpattern "pattuncolored" - withpen pencircle scaled 1/2 - withcolor 0.7 blue; - fi + picture tex; + tex = mpliboutlinetext.p ("\bf \TeX"); + for i=1 upto mpliboutlinenum: + j:=0; + for item within mpliboutlinepic[i]: + j:=j+1; + draw pathpart item scaled 10 + if j < length mpliboutlinepic[i]: + withpostscript "collect" + else: + withpattern "pattuncolored" + withfademethod "linear" + withfadebbox (10 llcorner tex, 10 urcorner tex) + withpen pencircle scaled 1/2 + withcolor (i/4)[red,blue] + fi; + endfor endfor \endmpfig \tracingcommands0 |