texlive[71342] Master/texmf-dist: luamplib (23may24)

commits+karl at tug.org commits+karl at tug.org
Fri May 24 22:57:53 CEST 2024


Revision: 71342
          https://tug.org/svn/texlive?view=revision&revision=71342
Author:   karl
Date:     2024-05-24 22:57:52 +0200 (Fri, 24 May 2024)
Log Message:
-----------
luamplib (23may24)

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-05-24 20:57:44 UTC (rev 71341)
+++ trunk/Master/texmf-dist/doc/luatex/luamplib/NEWS	2024-05-24 20:57:52 UTC (rev 71342)
@@ -1,8 +1,12 @@
                        History of the luamplib package
 
+2024/05/24 2.31.1
+   * fix bugs in outlinetext routine
+   * improve rule treatment in graphictext
+
 2024/05/21 2.31.0
    * provide a new metapost operator 'mpliboutlinetext', which mimicks
-   metafun's 'outlinetext'. The syntax is the same as metafun's.
+   metafun's 'outlinetext'. The syntax is the same as metafun's. (#133)
 
 2024/05/10 2.30.0
    * provide a new metapost operator 'mplibglyph', which returns a metapost

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-05-24 20:57:44 UTC (rev 71341)
+++ trunk/Master/texmf-dist/doc/luatex/luamplib/test-luamplib-latex.tex	2024-05-24 20:57:52 UTC (rev 71342)
@@ -175,7 +175,7 @@
 \par
 \begin{mplibcode}
 beginfig(1)
-draw mplibgraphictext "\bfseries Funny"
+  draw mplibgraphictext "\bfseries Funny$\sqrt{2}$"
   fakebold 2 % fontspec option
   drawcolor blue fillcolor "red!50" % l3color expression
   scaled 3 rotated 30 ;

Modified: trunk/Master/texmf-dist/doc/luatex/luamplib/test-luamplib-plain.tex
===================================================================
--- trunk/Master/texmf-dist/doc/luatex/luamplib/test-luamplib-plain.tex	2024-05-24 20:57:44 UTC (rev 71341)
+++ trunk/Master/texmf-dist/doc/luatex/luamplib/test-luamplib-plain.tex	2024-05-24 20:57:52 UTC (rev 71342)
@@ -167,7 +167,7 @@
 \par
 \mplibcode
 beginfig(1) % in dvi mode, not work for type1 font
-draw mplibgraphictext "\bf Funny"
+draw mplibgraphictext "\bf Funny$\sqrt{2}$"
   fakebold 2 % fontspec option
   drawcolor blue fillcolor .5[red,white]
   scaled 3 rotated 30 ;

Modified: trunk/Master/texmf-dist/source/luatex/luamplib/luamplib.dtx
===================================================================
--- trunk/Master/texmf-dist/source/luatex/luamplib/luamplib.dtx	2024-05-24 20:57:44 UTC (rev 71341)
+++ trunk/Master/texmf-dist/source/luatex/luamplib/luamplib.dtx	2024-05-24 20:57:52 UTC (rev 71342)
@@ -85,7 +85,7 @@
 %<*driver>
 \NeedsTeXFormat{LaTeX2e}
 \ProvidesFile{luamplib.drv}%
-  [2024/05/21 v2.31.0 Interface for using the mplib library]%
+  [2024/05/24 v2.31.1 Interface for using the mplib library]%
 \documentclass{ltxdoc}
 \usepackage{metalogo,multicol,mdwlist,fancyvrb,xspace}
 \usepackage[x11names]{xcolor}
@@ -112,7 +112,7 @@
   ItalicFont  = {Linux Libertine O Italic},
   SlantedFont = {Linux Libertine O Italic},
 ]{Linux Libertine O}
-\setmonofont[Ligatures=TeX,Scale=MatchLowercase]{InconsolataN}
+\setmonofont[Scale=MatchLowercase]{InconsolataN}
 %setsansfont[Ligatures=TeX]{Linux Biolinum O}
 \setsansfont[Ligatures=TeX,Scale=MatchLowercase]{Iwona Medium}
 %setmathfont{XITS Math}
@@ -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/05/21 v2.31.0}
+% \date{2024/05/24 v2.31.1}
 %
 % \maketitle
 %
@@ -592,8 +592,8 @@
 
 luatexbase.provides_module {
   name          = "luamplib",
-  version       = "2.31.0",
-  date          = "2024/05/21",
+  version       = "2.31.1",
+  date          = "2024/05/24",
   description   = "Lua package to typeset Metapost with LuaTeX's MPLib.",
 }
 
@@ -834,7 +834,6 @@
   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}
@@ -943,7 +942,6 @@
   else
     local t, e, l = result.term, result.error, result.log
 %    \end{macrocode}
-%
 %    log has more information than term, so log first (2021/08/02)
 %    \begin{macrocode}
     local log = l or t or "no-term"
@@ -962,7 +960,6 @@
     elseif prevlog then
       log = prevlog..log
 %    \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 an info,
@@ -985,7 +982,6 @@
     ini_version = true,
     find_file   = luamplib.finder,
 %    \end{macrocode}
-%
 %    Make use of |make_text| and |run_script|, which will co-operate
 %    with \LuaTeX's |tex.runtoks|. And we
 %    provide |numbersystem| option since v2.4. Default value ``|scaled|''
@@ -1001,7 +997,6 @@
     extensions  = 1,
   }
 %    \end{macrocode}
-%
 %    Append our own MetaPost preamble to the preamble above.
 %    \begin{macrocode}
   local preamble = tableconcat{
@@ -1027,7 +1022,6 @@
 %    \begin{macrocode}
 local function process (data, instancename)
 %    \end{macrocode}
-%
 %    The workaround of issue \#70 seems to be unnecessary, as we use
 %    |make_text| now.
 %    \begin{verbatim}
@@ -1509,14 +1503,95 @@
 %
 %    luamplib's mplibgraphictext operator
 %    \begin{macrocode}
+local running = -1073741824
 local emboldenfonts = { }
-local function embolden (head, fakebold)
-  local curr = head
+local function getemboldenwidth (curr, fakebold)
+  local width = emboldenfonts.width
+  if not width then
+    local f
+    local function getglyph(n)
+      while n do
+        if n.head then
+          getglyph(n.head)
+        elseif n.font and n.font > 0 then
+          f = n.font; break
+        end
+        n = node.getnext(n)
+      end
+    end
+    getglyph(curr)
+    width = font.getcopy(f or font.current()).size * fakebold / factor * 10
+    emboldenfonts.width = width
+  end
+  return width
+end
+local function getrulewhatsit (line, wd, ht, dp)
+  line, wd, ht, dp = line/1000, wd/factor, ht/factor, dp/factor
+  local pl
+  local fmt = "%f w %f %f %f %f re %s"
+  if pdfmode then
+    pl = node.new("whatsit","pdf_literal")
+    pl.mode = 0
+  else
+    fmt = "pdf:content "..fmt
+    pl = node.new("whatsit","special")
+  end
+  pl.data = fmt:format(line, 0, -dp, wd, ht+dp, "B")
+  local ss = node.new"glue"
+  node.setglue(ss, 0, 65536, 65536, 2, 2)
+  pl.next = ss
+  return pl
+end
+local function getrulemetric (box, curr, bp)
+  local wd,ht,dp = curr.width, curr.height, curr.depth
+  wd = wd == running and box.width  or wd
+  ht = ht == running and box.height or ht
+  dp = dp == running and box.depth  or dp
+  if bp then
+    return wd/factor, ht/factor, dp/factor
+  end
+  return wd, ht, dp
+end
+local function embolden (box, curr, fakebold)
+  local head = curr
   while curr do
     if curr.head then
-      embolden(curr.head, fakebold)
-    elseif curr.leader and curr.leader.head then
-      embolden(curr.leader.head, fakebold)
+      curr.head = embolden(curr, curr.head, fakebold)
+    elseif curr.replace then
+      curr.replace = embolden(box, curr.replace, fakebold)
+    elseif curr.leader then
+      if curr.leader.head then
+        curr.leader.head = embolden(curr.leader, curr.leader.head, fakebold)
+      elseif curr.leader.id == node.id"rule" then
+        local glue = node.effective_glue(curr, box)
+        local line = getemboldenwidth(curr, fakebold)
+        local wd,ht,dp = getrulemetric(box, curr.leader)
+        if box.id == node.id"hlist" then
+          wd = glue
+        else
+          ht, dp = 0, glue
+        end
+        local pl = getrulewhatsit(line, wd, ht, dp)
+        local pack = box.id == node.id"hlist" and node.hpack or node.vpack
+        local list = pack(pl, glue, "exactly")
+        head = node.insert_after(head, curr, list)
+        head, curr = node.remove(head, curr)
+      end
+    elseif curr.id == node.id"rule" and curr.subtype == 0 then
+      local line = getemboldenwidth(curr, fakebold)
+      local wd,ht,dp = getrulemetric(box, curr)
+      if box.id == node.id"vlist" then
+        ht, dp = 0, ht+dp
+      end
+      local pl = getrulewhatsit(line, wd, ht, dp)
+      local list
+      if box.id == node.id"hlist" then
+        list = node.hpack(pl, wd, "exactly")
+      else
+        list = node.vpack(pl, ht+dp, "exactly")
+      end
+      head = node.insert_after(head, curr, list)
+      head, curr = node.remove(head, curr)
     elseif curr.id == node.id"glyph" and curr.font > 0 then
       local f = curr.font
       local i = emboldenfonts[f]
@@ -1523,8 +1598,9 @@
       if not i then
         if pdfmode then
           local ft = font.getcopy(f)
-          ft.mode = 2
-          ft.width = ft.size * fakebold / 6578.176
+          width = ft.size * fakebold / factor * 10
+          emboldenfonts.width = width
+          ft.mode, ft.width = 2, width
           i = font.define(ft)
         else
           local ft = font.getfont(f) or font.getcopy(f)
@@ -1532,7 +1608,7 @@
             goto skip_type1
           end
           local name = ft.name:gsub('"',''):gsub(';$','')
-          name = format('%s;embolden=%s',name,fakebold)
+          name = format('%s;embolden=%s;',name,fakebold)
           _, i = fonts.constructors.readanddefine(name,ft.size)
         end
         emboldenfonts[f] = i
@@ -1542,6 +1618,7 @@
     ::skip_type1::
     curr = node.getnext(curr)
   end
+  return head
 end
 local function graphictextcolor (col, filldraw)
   if col:find"^[%d%.:]+$" then
@@ -1568,7 +1645,8 @@
 luamplib.graphictext = function (text, fakebold, fc, dc)
   local fmt = process_tex_text(text):sub(1,-2)
   local id = tonumber(fmt:match"mplibtexboxid=(%d+):")
-  embolden(texgetbox(id).head, fakebold)
+  local box = texgetbox(id)
+  box.head = embolden(box, box.head, fakebold)
   local fill = graphictextcolor(fc,"fill")
   local draw = graphictextcolor(dc,"draw")
   local bc = pdfmode and "" or "pdf:bc "
@@ -1667,7 +1745,7 @@
     local fontdata = font.getfont(fid) or font.getcopy(fid)
     filename, subfont, kind = fontdata.filename, fontdata.subfont, fontdata.format
     instance = fontdata.specification and fontdata.specification.instance
-    filename = filename:gsub("^harfloaded:","")
+    filename = filename and filename:gsub("^harfloaded:","")
   else
     local name
     f = f:match"^%s*(.+)%s*$"
@@ -1745,15 +1823,13 @@
 local outline_horz, outline_vert
 function outline_vert (res, box, curr, xshift, yshift)
   local b2u = box.dir == "LTL"
-  local dy = (b2u and -(box.depth or 0) or (box.height or 0))/factor
+  local dy = (b2u and -box.depth or box.height)/factor
   local ody = dy
   while curr do
     if curr.id == node.id"rule" then
-      local ht, dp = curr.height/factor, curr.depth/factor
+      local wd, ht, dp = getrulemetric(box, curr, true)
       local hd = ht + dp
       if hd ~= 0 then
-        local wd = curr.width
-        wd = (wd == -1073741824 and box.width or wd)/factor
         dy = dy + (b2u and dp or -ht)
         if wd ~= 0 and curr.subtype == 0 then
           res[#res+1] = rulefmt:format(#res+1, wd, hd, xshift+wd/2, yshift+dy+(ht-dp)/2)
@@ -1762,14 +1838,13 @@
       end
     elseif curr.id == node.id"glue" then
       local vwidth = node.effective_glue(curr,box)/factor
-      dy = dy + (b2u and vwidth or 0)
       if curr.leader then
         local curr, kind = curr.leader, curr.subtype
         if curr.id == node.id"rule" then
-          local wd = curr.width/factor
+          local wd = getrulemetric(box, curr, true)
           if wd ~= 0 then
             local hd = vwidth
-            local dy = dy - hd
+            local dy = dy + (b2u and 0 or -hd)
             if hd ~= 0 and curr.subtype == 0 then
               res[#res+1] = rulefmt:format(#res+1, wd, hd, xshift+wd/2, yshift+dy+hd/2)
             end
@@ -1777,8 +1852,7 @@
         elseif curr.head then
           local hd = (curr.height + curr.depth)/factor
           if hd <= vwidth then
-            local dy = b2u and dy-vwidth or dy
-            local n, iy = 0, 0
+            local dy, n, iy = dy, 0, 0
             if kind == 100 or kind == 103 then -- todo: gleaders
               local ady = abs(ody - dy)
               local ndy = math.ceil(ady / hd) * hd
@@ -1806,7 +1880,7 @@
           end
         end
       end
-      dy = dy - (b2u and 0 or vwidth)
+      dy = dy + (b2u and vwidth or -vwidth)
     elseif curr.id == node.id"kern" then
       dy = dy + curr.kern/factor * (b2u and 1 or -1)
     elseif curr.id == node.id"vlist" then
@@ -1822,24 +1896,23 @@
   end
   return res
 end
-function outline_horz (res, box, curr, xshift, yshift)
+function outline_horz (res, box, curr, xshift, yshift, discwd)
   local r2l = box.dir == "TRT"
-  local dx = r2l and (box.width or 0)/factor or 0
+  local dx = r2l and (discwd or box.width/factor) or 0
   local dirs = { { dir = r2l, dx = dx } }
-  local odx = dx
   while curr do
     if curr.id == node.id"dir" then
       local sign, dir = curr.dir:match"(.)(...)"
       local level, newdir = curr.level, r2l
       if sign == "+" then
-        local n = node.getnext(curr)
-        while n do
-          if n.id == node.id"dir" and n.level+1 == level then break end
-          n = node.getnext(n)
-        end
-        n = n or node.tail(curr)
         newdir = dir == "TRT"
         if r2l ~= newdir then
+          local n = node.getnext(curr)
+          while n do
+            if n.id == node.id"dir" and n.level+1 == level then break end
+            n = node.getnext(n)
+          end
+          n = n or node.tail(curr)
           dx = dx + node.rangedimensions(box, curr, n)/factor * (newdir and 1 or -1)
         end
         dirs[level] = { dir = r2l, dx = dx }
@@ -1886,17 +1959,14 @@
       res[#res+1] = format("mplibpic[%i]:=%s xscaled %f yscaled %f slanted %f shifted (%f,%f);",
                            #res+1, image, xscale, yscale, slant, xpos, ypos)
       dx = dx + (r2l and 0 or curr.width/factor*expand)
-    elseif curr.id == node.id"disc" then
+    elseif curr.replace then
       local width = node.dimensions(curr.replace)/factor
       dx = dx - (r2l and width or 0)
-      res = outline_horz(res, curr, curr.replace, xshift+dx, yshift)
+      res = outline_horz(res, box, curr.replace, xshift+dx, yshift, width)
       dx = dx + (r2l and 0 or width)
     elseif curr.id == node.id"rule" then
-      local wd = curr.width/factor
+      local wd, ht, dp = getrulemetric(box, curr, true)
       if wd ~= 0 then
-        local ht, dp = curr.height, curr.depth
-        ht = (ht == -1073741824 and box.height or ht)/factor
-        dp = (dp == -1073741824 and box.depth  or dp)/factor
         local hd = ht + dp
         dx = dx - (r2l and wd or 0)
         if hd ~= 0 and curr.subtype == 0 then
@@ -1910,10 +1980,10 @@
       if curr.leader then
         local curr, kind = curr.leader, curr.subtype
         if curr.id == node.id"rule" then
-          local ht, dp = curr.height/factor, curr.depth/factor
+          local wd, ht, dp = getrulemetric(box, curr, true)
           local hd = ht + dp
           if hd ~= 0 then
-            local wd = width
+            wd = width
             if wd ~= 0 and curr.subtype == 0 then
               res[#res+1] = rulefmt:format(#res+1, wd, hd, xshift+dx+wd/2, yshift+(ht-dp)/2)
             end
@@ -1924,7 +1994,7 @@
             local dx = r2l and dx+width or dx
             local n, ix = 0, 0
             if kind == 100 or kind == 103 then -- todo: gleaders
-              local adx = abs(dx-odx)
+              local adx = abs(dx-dirs[1].dx)
               local ndx = math.ceil(adx / wd) * wd
               local diff = ndx - adx
               n = (width-diff) // wd
@@ -2214,7 +2284,6 @@
   texboxes.localid = 4096
 
 %    \end{macrocode}
-%
 %    This is needed for legacy behavior
 %    \begin{macrocode}
   if luamplib.legacy_verbatimtex then
@@ -2236,7 +2305,6 @@
     :gsub(btex_etex, "btex %1 etex ")
     :gsub(verbatimtex_etex, "verbatimtex %1 etex;")
 %    \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.
@@ -2255,7 +2323,6 @@
     run_tex_code(format("\\mplibtmptoks\\expandafter{\\expanded{%s}}",data))
     data = texgettoks"mplibtmptoks"
 %    \end{macrocode}
-%
 %    Next line to address issue \#55
 %    \begin{macrocode}
     :gsub("##", "#")
@@ -2832,7 +2899,6 @@
         local llx, lly, urx, ury = bbox[1], bbox[2], bbox[3], bbox[4] -- faster than unpack
         if urx < llx then
 %    \end{macrocode}
-%
 %    luamplib silently ignores this invalid figure for those
 %    that do not contain |beginfig ... endfig|. (issue \#70)
 %    Original code of ConTeXt general was:
@@ -2858,7 +2924,6 @@
               local object        = objects[o]
               local objecttype    = object.type
 %    \end{macrocode}
-%
 %    The following 6 lines are part of |btex...etex| patch.
 %    Again, colors are processed at this stage.
 %    \begin{macrocode}
@@ -2879,7 +2944,6 @@
                 miterlimit, linecap, linejoin, dashed = -1, -1, -1, false
               elseif objecttype == "special" then
 %    \end{macrocode}
-%
 %    Collect \TeX\ codes that will be executed after flushing.
 %    Legacy behavior.
 %    \begin{macrocode}
@@ -3036,7 +3100,6 @@
                     end
                   end
 %    \end{macrocode}
-%
 %    Added to ConTeXt general: post-object color and shading stuff.
 %    \begin{macrocode}
                   if shade_no then -- shading
@@ -3107,7 +3170,7 @@
 \else
   \NeedsTeXFormat{LaTeX2e}
   \ProvidesPackage{luamplib}
-    [2024/05/21 v2.31.0 mplib package for LuaTeX]
+    [2024/05/24 v2.31.1 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-05-24 20:57:44 UTC (rev 71341)
+++ trunk/Master/texmf-dist/tex/luatex/luamplib/luamplib.lua	2024-05-24 20:57:52 UTC (rev 71342)
@@ -11,8 +11,8 @@
 
 luatexbase.provides_module {
   name          = "luamplib",
-  version       = "2.31.0",
-  date          = "2024/05/21",
+  version       = "2.31.1",
+  date          = "2024/05/24",
   description   = "Lua package to typeset Metapost with LuaTeX's MPLib.",
 }
 
@@ -682,14 +682,95 @@
   return colorsplit(res)
 end
 
+local running = -1073741824
 local emboldenfonts = { }
-local function embolden (head, fakebold)
-  local curr = head
+local function getemboldenwidth (curr, fakebold)
+  local width = emboldenfonts.width
+  if not width then
+    local f
+    local function getglyph(n)
+      while n do
+        if n.head then
+          getglyph(n.head)
+        elseif n.font and n.font > 0 then
+          f = n.font; break
+        end
+        n = node.getnext(n)
+      end
+    end
+    getglyph(curr)
+    width = font.getcopy(f or font.current()).size * fakebold / factor * 10
+    emboldenfonts.width = width
+  end
+  return width
+end
+local function getrulewhatsit (line, wd, ht, dp)
+  line, wd, ht, dp = line/1000, wd/factor, ht/factor, dp/factor
+  local pl
+  local fmt = "%f w %f %f %f %f re %s"
+  if pdfmode then
+    pl = node.new("whatsit","pdf_literal")
+    pl.mode = 0
+  else
+    fmt = "pdf:content "..fmt
+    pl = node.new("whatsit","special")
+  end
+  pl.data = fmt:format(line, 0, -dp, wd, ht+dp, "B")
+  local ss = node.new"glue"
+  node.setglue(ss, 0, 65536, 65536, 2, 2)
+  pl.next = ss
+  return pl
+end
+local function getrulemetric (box, curr, bp)
+  local wd,ht,dp = curr.width, curr.height, curr.depth
+  wd = wd == running and box.width  or wd
+  ht = ht == running and box.height or ht
+  dp = dp == running and box.depth  or dp
+  if bp then
+    return wd/factor, ht/factor, dp/factor
+  end
+  return wd, ht, dp
+end
+local function embolden (box, curr, fakebold)
+  local head = curr
   while curr do
     if curr.head then
-      embolden(curr.head, fakebold)
-    elseif curr.leader and curr.leader.head then
-      embolden(curr.leader.head, fakebold)
+      curr.head = embolden(curr, curr.head, fakebold)
+    elseif curr.replace then
+      curr.replace = embolden(box, curr.replace, fakebold)
+    elseif curr.leader then
+      if curr.leader.head then
+        curr.leader.head = embolden(curr.leader, curr.leader.head, fakebold)
+      elseif curr.leader.id == node.id"rule" then
+        local glue = node.effective_glue(curr, box)
+        local line = getemboldenwidth(curr, fakebold)
+        local wd,ht,dp = getrulemetric(box, curr.leader)
+        if box.id == node.id"hlist" then
+          wd = glue
+        else
+          ht, dp = 0, glue
+        end
+        local pl = getrulewhatsit(line, wd, ht, dp)
+        local pack = box.id == node.id"hlist" and node.hpack or node.vpack
+        local list = pack(pl, glue, "exactly")
+        head = node.insert_after(head, curr, list)
+        head, curr = node.remove(head, curr)
+      end
+    elseif curr.id == node.id"rule" and curr.subtype == 0 then
+      local line = getemboldenwidth(curr, fakebold)
+      local wd,ht,dp = getrulemetric(box, curr)
+      if box.id == node.id"vlist" then
+        ht, dp = 0, ht+dp
+      end
+      local pl = getrulewhatsit(line, wd, ht, dp)
+      local list
+      if box.id == node.id"hlist" then
+        list = node.hpack(pl, wd, "exactly")
+      else
+        list = node.vpack(pl, ht+dp, "exactly")
+      end
+      head = node.insert_after(head, curr, list)
+      head, curr = node.remove(head, curr)
     elseif curr.id == node.id"glyph" and curr.font > 0 then
       local f = curr.font
       local i = emboldenfonts[f]
@@ -696,8 +777,9 @@
       if not i then
         if pdfmode then
           local ft = font.getcopy(f)
-          ft.mode = 2
-          ft.width = ft.size * fakebold / 6578.176
+          width = ft.size * fakebold / factor * 10
+          emboldenfonts.width = width
+          ft.mode, ft.width = 2, width
           i = font.define(ft)
         else
           local ft = font.getfont(f) or font.getcopy(f)
@@ -705,7 +787,7 @@
             goto skip_type1
           end
           local name = ft.name:gsub('"',''):gsub(';$','')
-          name = format('%s;embolden=%s',name,fakebold)
+          name = format('%s;embolden=%s;',name,fakebold)
           _, i = fonts.constructors.readanddefine(name,ft.size)
         end
         emboldenfonts[f] = i
@@ -715,6 +797,7 @@
     ::skip_type1::
     curr = node.getnext(curr)
   end
+  return head
 end
 local function graphictextcolor (col, filldraw)
   if col:find"^[%d%.:]+$" then
@@ -741,7 +824,8 @@
 luamplib.graphictext = function (text, fakebold, fc, dc)
   local fmt = process_tex_text(text):sub(1,-2)
   local id = tonumber(fmt:match"mplibtexboxid=(%d+):")
-  embolden(texgetbox(id).head, fakebold)
+  local box = texgetbox(id)
+  box.head = embolden(box, box.head, fakebold)
   local fill = graphictextcolor(fc,"fill")
   local draw = graphictextcolor(dc,"draw")
   local bc = pdfmode and "" or "pdf:bc "
@@ -836,7 +920,7 @@
     local fontdata = font.getfont(fid) or font.getcopy(fid)
     filename, subfont, kind = fontdata.filename, fontdata.subfont, fontdata.format
     instance = fontdata.specification and fontdata.specification.instance
-    filename = filename:gsub("^harfloaded:","")
+    filename = filename and filename:gsub("^harfloaded:","")
   else
     local name
     f = f:match"^%s*(.+)%s*$"
@@ -910,15 +994,13 @@
 local outline_horz, outline_vert
 function outline_vert (res, box, curr, xshift, yshift)
   local b2u = box.dir == "LTL"
-  local dy = (b2u and -(box.depth or 0) or (box.height or 0))/factor
+  local dy = (b2u and -box.depth or box.height)/factor
   local ody = dy
   while curr do
     if curr.id == node.id"rule" then
-      local ht, dp = curr.height/factor, curr.depth/factor
+      local wd, ht, dp = getrulemetric(box, curr, true)
       local hd = ht + dp
       if hd ~= 0 then
-        local wd = curr.width
-        wd = (wd == -1073741824 and box.width or wd)/factor
         dy = dy + (b2u and dp or -ht)
         if wd ~= 0 and curr.subtype == 0 then
           res[#res+1] = rulefmt:format(#res+1, wd, hd, xshift+wd/2, yshift+dy+(ht-dp)/2)
@@ -927,14 +1009,13 @@
       end
     elseif curr.id == node.id"glue" then
       local vwidth = node.effective_glue(curr,box)/factor
-      dy = dy + (b2u and vwidth or 0)
       if curr.leader then
         local curr, kind = curr.leader, curr.subtype
         if curr.id == node.id"rule" then
-          local wd = curr.width/factor
+          local wd = getrulemetric(box, curr, true)
           if wd ~= 0 then
             local hd = vwidth
-            local dy = dy - hd
+            local dy = dy + (b2u and 0 or -hd)
             if hd ~= 0 and curr.subtype == 0 then
               res[#res+1] = rulefmt:format(#res+1, wd, hd, xshift+wd/2, yshift+dy+hd/2)
             end
@@ -942,8 +1023,7 @@
         elseif curr.head then
           local hd = (curr.height + curr.depth)/factor
           if hd <= vwidth then
-            local dy = b2u and dy-vwidth or dy
-            local n, iy = 0, 0
+            local dy, n, iy = dy, 0, 0
             if kind == 100 or kind == 103 then -- todo: gleaders
               local ady = abs(ody - dy)
               local ndy = math.ceil(ady / hd) * hd
@@ -971,7 +1051,7 @@
           end
         end
       end
-      dy = dy - (b2u and 0 or vwidth)
+      dy = dy + (b2u and vwidth or -vwidth)
     elseif curr.id == node.id"kern" then
       dy = dy + curr.kern/factor * (b2u and 1 or -1)
     elseif curr.id == node.id"vlist" then
@@ -987,24 +1067,23 @@
   end
   return res
 end
-function outline_horz (res, box, curr, xshift, yshift)
+function outline_horz (res, box, curr, xshift, yshift, discwd)
   local r2l = box.dir == "TRT"
-  local dx = r2l and (box.width or 0)/factor or 0
+  local dx = r2l and (discwd or box.width/factor) or 0
   local dirs = { { dir = r2l, dx = dx } }
-  local odx = dx
   while curr do
     if curr.id == node.id"dir" then
       local sign, dir = curr.dir:match"(.)(...)"
       local level, newdir = curr.level, r2l
       if sign == "+" then
-        local n = node.getnext(curr)
-        while n do
-          if n.id == node.id"dir" and n.level+1 == level then break end
-          n = node.getnext(n)
-        end
-        n = n or node.tail(curr)
         newdir = dir == "TRT"
         if r2l ~= newdir then
+          local n = node.getnext(curr)
+          while n do
+            if n.id == node.id"dir" and n.level+1 == level then break end
+            n = node.getnext(n)
+          end
+          n = n or node.tail(curr)
           dx = dx + node.rangedimensions(box, curr, n)/factor * (newdir and 1 or -1)
         end
         dirs[level] = { dir = r2l, dx = dx }
@@ -1051,17 +1130,14 @@
       res[#res+1] = format("mplibpic[%i]:=%s xscaled %f yscaled %f slanted %f shifted (%f,%f);",
                            #res+1, image, xscale, yscale, slant, xpos, ypos)
       dx = dx + (r2l and 0 or curr.width/factor*expand)
-    elseif curr.id == node.id"disc" then
+    elseif curr.replace then
       local width = node.dimensions(curr.replace)/factor
       dx = dx - (r2l and width or 0)
-      res = outline_horz(res, curr, curr.replace, xshift+dx, yshift)
+      res = outline_horz(res, box, curr.replace, xshift+dx, yshift, width)
       dx = dx + (r2l and 0 or width)
     elseif curr.id == node.id"rule" then
-      local wd = curr.width/factor
+      local wd, ht, dp = getrulemetric(box, curr, true)
       if wd ~= 0 then
-        local ht, dp = curr.height, curr.depth
-        ht = (ht == -1073741824 and box.height or ht)/factor
-        dp = (dp == -1073741824 and box.depth  or dp)/factor
         local hd = ht + dp
         dx = dx - (r2l and wd or 0)
         if hd ~= 0 and curr.subtype == 0 then
@@ -1075,10 +1151,10 @@
       if curr.leader then
         local curr, kind = curr.leader, curr.subtype
         if curr.id == node.id"rule" then
-          local ht, dp = curr.height/factor, curr.depth/factor
+          local wd, ht, dp = getrulemetric(box, curr, true)
           local hd = ht + dp
           if hd ~= 0 then
-            local wd = width
+            wd = width
             if wd ~= 0 and curr.subtype == 0 then
               res[#res+1] = rulefmt:format(#res+1, wd, hd, xshift+dx+wd/2, yshift+(ht-dp)/2)
             end
@@ -1089,7 +1165,7 @@
             local dx = r2l and dx+width or dx
             local n, ix = 0, 0
             if kind == 100 or kind == 103 then -- todo: gleaders
-              local adx = abs(dx-odx)
+              local adx = abs(dx-dirs[1].dx)
               local ndx = math.ceil(adx / wd) * wd
               local diff = ndx - adx
               n = (width-diff) // wd

Modified: trunk/Master/texmf-dist/tex/luatex/luamplib/luamplib.sty
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/luamplib/luamplib.sty	2024-05-24 20:57:44 UTC (rev 71341)
+++ trunk/Master/texmf-dist/tex/luatex/luamplib/luamplib.sty	2024-05-24 20:57:52 UTC (rev 71342)
@@ -14,7 +14,7 @@
 \else
   \NeedsTeXFormat{LaTeX2e}
   \ProvidesPackage{luamplib}
-    [2024/05/21 v2.31.0 mplib package for LuaTeX]
+    [2024/05/24 v2.31.1 mplib package for LuaTeX]
   \ifx\newluafunction\@undefined
   \input ltluatex
   \fi



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