texlive[71745] Master/texmf-dist: luamplib (8jul24)

commits+karl at tug.org commits+karl at tug.org
Mon Jul 8 22:15:15 CEST 2024


Revision: 71745
          https://tug.org/svn/texlive?view=revision&revision=71745
Author:   karl
Date:     2024-07-08 22:15:15 +0200 (Mon, 08 Jul 2024)
Log Message:
-----------
luamplib (8jul24)

Modified Paths:
--------------
    trunk/Master/texmf-dist/doc/luatex/luamplib/NEWS
    trunk/Master/texmf-dist/doc/luatex/luamplib/luamplib.pdf
    trunk/Master/texmf-dist/doc/luatex/luamplib/test-luamplib-latex.tex
    trunk/Master/texmf-dist/doc/luatex/luamplib/test-luamplib-plain.tex
    trunk/Master/texmf-dist/source/luatex/luamplib/luamplib.dtx
    trunk/Master/texmf-dist/tex/luatex/luamplib/luamplib.lua
    trunk/Master/texmf-dist/tex/luatex/luamplib/luamplib.sty

Modified: trunk/Master/texmf-dist/doc/luatex/luamplib/NEWS
===================================================================
--- trunk/Master/texmf-dist/doc/luatex/luamplib/NEWS	2024-07-08 20:15:05 UTC (rev 71744)
+++ trunk/Master/texmf-dist/doc/luatex/luamplib/NEWS	2024-07-08 20:15:15 UTC (rev 71745)
@@ -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

Modified: trunk/Master/texmf-dist/doc/luatex/luamplib/luamplib.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/luatex/luamplib/test-luamplib-latex.tex
===================================================================
--- trunk/Master/texmf-dist/doc/luatex/luamplib/test-luamplib-latex.tex	2024-07-08 20:15:05 UTC (rev 71744)
+++ trunk/Master/texmf-dist/doc/luatex/luamplib/test-luamplib-latex.tex	2024-07-08 20:15:15 UTC (rev 71745)
@@ -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 @@
   \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

Modified: trunk/Master/texmf-dist/doc/luatex/luamplib/test-luamplib-plain.tex
===================================================================
--- trunk/Master/texmf-dist/doc/luatex/luamplib/test-luamplib-plain.tex	2024-07-08 20:15:05 UTC (rev 71744)
+++ trunk/Master/texmf-dist/doc/luatex/luamplib/test-luamplib-plain.tex	2024-07-08 20:15:15 UTC (rev 71745)
@@ -261,17 +261,23 @@
   \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

Modified: trunk/Master/texmf-dist/source/luatex/luamplib/luamplib.dtx
===================================================================
--- trunk/Master/texmf-dist/source/luatex/luamplib/luamplib.dtx	2024-07-08 20:15:05 UTC (rev 71744)
+++ trunk/Master/texmf-dist/source/luatex/luamplib/luamplib.dtx	2024-07-08 20:15:15 UTC (rev 71745)
@@ -85,7 +85,7 @@
 %<*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 @@
 % \author{Hans Hagen, Taco Hoekwater, Elie Roux, Philipp Gesang and Kim Dohyun\\
 % Maintainer: LuaLaTeX Maintainers ---
 % Support: \email{lualatex-dev at tug.org}}
-% \date{2024/07/03 v2.32.4}
+% \date{2024/07/08 v2.33.0}
 %
 % \maketitle
 %
@@ -562,7 +562,8 @@
 %     \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,7 +605,7 @@
 %      \begin{mppattern}{pattuncolored}
 %        [
 %          colored = false,
-%          matrix = "rotated 30",
+%          matrix = "slanted .3 rotated 30",
 %        ]
 %        \tiny\TeX
 %      \end{mppattern}
@@ -611,25 +612,69 @@
 %
 %      \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 @@
 
 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 @@
 %    \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 @@
       return buffer
     end
     buffer = {}
-    mpprint(buffer, table.unpack(res))
+    mpprint(buffer, tableunpack(res))
     return tableconcat(buffer)
   end
   return ""
@@ -1576,11 +1622,41 @@
 %     \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_ at tempa]],
     },ccexplat)
-    local name = get_macro'mplib_ at tempa':match'{(.-)}{.+}'
+    local name, value = get_macro'mplib_ at tempa':match'{(.-)}{(.-)}'
     local t, obj = res:explode()
     if pdfmode then
       obj = format("%s 0 R", ltx.pdf.object_id( t[1]:sub(2,-1) ))
@@ -1587,8 +1663,7 @@
     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 @@
   & 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.pgfpattern = "pgf at sys@addpdfresource at patterns@plain"
 pdfetcs.pgfcolorspace = "pgf at sys@addpdfresource at 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 @@
   "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 @@
   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 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{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,7 +3455,7 @@
               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
@@ -3263,6 +3462,7 @@
               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 @@
                   end
                 end
               end
+              if fading_ then -- fading
+                stop_pdf_code()
+              end
               if tr_opaq then -- opacity
                 stop_pdf_code()
               end
@@ -3503,7 +3706,7 @@
 \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

Modified: trunk/Master/texmf-dist/tex/luatex/luamplib/luamplib.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/luamplib/luamplib.lua	2024-07-08 20:15:05 UTC (rev 71744)
+++ trunk/Master/texmf-dist/tex/luatex/luamplib/luamplib.lua	2024-07-08 20:15:15 UTC (rev 71745)
@@ -11,8 +11,8 @@
 
 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.",
 }
 
@@ -60,6 +60,7 @@
 
 local tableconcat = table.concat
 local tableinsert = table.insert
+local tableunpack = table.unpack
 local texsprint   = tex.sprint
 local texgettoks  = tex.gettoks
 local texgetbox   = tex.getbox
@@ -580,7 +581,7 @@
       return buffer
     end
     buffer = {}
-    mpprint(buffer, table.unpack(res))
+    mpprint(buffer, tableunpack(res))
     return tableconcat(buffer)
   end
   return ""
@@ -660,7 +661,7 @@
     run_tex_code({
       [[\color_export:nnN{]], str, [[}{backend}\mplib_ at tempa]],
     },ccexplat)
-    local name = get_macro'mplib_ at tempa':match'{(.-)}{.+}'
+    local name, value = get_macro'mplib_ at tempa':match'{(.-)}{(.-)}'
     local t, obj = res:explode()
     if pdfmode then
       obj = format("%s 0 R", ltx.pdf.object_id( t[1]:sub(2,-1) ))
@@ -667,8 +668,7 @@
     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
@@ -1417,6 +1417,39 @@
   & 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;
@@ -1720,19 +1753,29 @@
 pdfetcs.pgfpattern = "pgf at sys@addpdfresource at patterns@plain"
 pdfetcs.pgfcolorspace = "pgf at sys@addpdfresource at 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
 
@@ -1785,12 +1828,9 @@
   "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 {
@@ -1822,21 +1862,22 @@
   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
 
 local function sh_pdfpageresources(shtype,domain,colorspace,ca,cb,coordinates,steps,fractions)
@@ -1970,15 +2011,14 @@
       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)
@@ -2215,6 +2255,86 @@
   patt.done = true
 end
 
+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
+
 function luamplib.flush (result,flusher)
   if result then
     local figures = result.fig
@@ -2244,6 +2364,7 @@
               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
@@ -2407,6 +2528,9 @@
                   end
                 end
               end
+              if fading_ then -- fading
+                stop_pdf_code()
+              end
               if tr_opaq then -- opacity
                 stop_pdf_code()
               end

Modified: trunk/Master/texmf-dist/tex/luatex/luamplib/luamplib.sty
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/luamplib/luamplib.sty	2024-07-08 20:15:05 UTC (rev 71744)
+++ trunk/Master/texmf-dist/tex/luatex/luamplib/luamplib.sty	2024-07-08 20:15:15 UTC (rev 71745)
@@ -14,7 +14,7 @@
 \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



More information about the tex-live-commits mailing list.