From 3c7932585aec3f06089fbbcda80b38363d7f2f55 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Sun, 11 Sep 2022 20:44:40 +0000 Subject: luapstricks (11sep22) git-svn-id: svn://tug.org/texlive/trunk@64345 c570f23f-e606-0410-a88d-b1316a301751 --- .../tex/lualatex/luapstricks/luapstricks.lua | 228 +++++++++------------ 1 file changed, 92 insertions(+), 136 deletions(-) diff --git a/Master/texmf-dist/tex/lualatex/luapstricks/luapstricks.lua b/Master/texmf-dist/tex/lualatex/luapstricks/luapstricks.lua index 874d141206b..5482582d153 100644 --- a/Master/texmf-dist/tex/lualatex/luapstricks/luapstricks.lua +++ b/Master/texmf-dist/tex/lualatex/luapstricks/luapstricks.lua @@ -18,8 +18,8 @@ if luatexbase then luatexbase.provides_module { name = 'luapstricks', - version = 'v0.5', - date = '2022-04-20', + version = 'v0.6', + date = '2022-09-10', description = 'PSTricks backend for LuaLaTeX', } end @@ -29,6 +29,13 @@ local late_lua_sub = node.subtype'late_lua' local pdfprint = vf.pdf -- Set later to have the right mode local function gobble() end +local function no_pdfprint_allowed() + pdfprint = gobble -- Don't warn more than once for each code block + tex.error("luapstricks: Graphics in immediate code segment", { + "There was an attempt to trigger drawing commands in an immediate code block. \z + This isn't allowed and will therefore be ignored." + }) +end local pi = math.pi local two_pi = 2*pi @@ -4055,77 +4062,55 @@ function execute_string(str, context) end end ---[[ - local readstate = status.readstate or status - local context = string.format('%s:%i', readstate.filename, readstate.linenumber) - local tokens = token.scan_argument(true) - local n = node.new('whatsit', late_lua_sub) - setwhatsitfield(n, 'data', function() - assert(not ps_tokens) - ps_tokens = tokens - ps_context = context - end) - local nn = node.new('glyph') - nn.subtype = 256 - nn.font, nn.char = fid, 0x1F3A8 - n.next = nn - if tex.nest.ptr == 0 then - -- Main vertical list. Here we might appear before the page starts properly - -- and should not freeze page specifications. Since we don't have any outer dimensions, - -- we can ensure this by sneaking our node into the current page list whithout going though - -- build_page. - tex.triggerbuildpage() -- First ensure that everything else is contributed properly. - tex.lists.page_head = node.insert_after(tex.lists.page_head, nil, n) - else - node.write(n) - end -end -]] -local func = luatexbase.new_luafunction'luaPSTheader' -token.set_lua('luaPSTheader', func, 'protected') -lua.get_functions_table()[func] = function() - local is_inline = token.scan_keyword'inline' - local readstate = status.readstate or status - local context = is_inline and string.format('%s:%i', readstate.filename, readstate.linenumber) - local data = token.scan_argument(true) - local n = node.new('whatsit', late_lua_sub) - setwhatsitfield(n, 'data', function() - if not is_inline then - context = data - local f = io.open(kpse.find_file(data, 'PostScript header'), 'r') - data = f:read'a' - f:close() - end - local stack_depth = #operand_stack - - local x, y = pdf.getpos() - local height = #operand_stack +-- If x, y shall be present iff direct ~= 'immediate' +local function outer_execute(tokens, direct, context, x, y) + local TeXDict = userdict.value.TeXDict.value + local saved_ocount = TeXDict.ocount + local height = #operand_stack + TeXDict.ocount = height + local graphics_height + if direct ~= 'immediate' then operand_stack[height + 1], operand_stack[height + 2] = x/65781.76, y/65781.76 - systemdict.value.moveto() - - local saved_pdfprint = pdfprint - pdfprint = function(s) return pdf.print('direct', s .. '\n') end - execute_string(data, context) - flush_delayed() - pdfprint = saved_pdfprint - if #operand_stack ~= stack_depth then - error'Unexpected values on operand stack' + if direct then + systemdict.value.moveto() + else + graphics_height = #graphics_stack + systemdict.value.gsave() + systemdict.value.translate() end - end) - node.write(n) -end - ---[[ -local func = luatexbase.new_luafunction'showPS' -token.set_lua('showPS', func, 'protected') -lua.get_functions_table()[func] = function() - local command = token.scan_argument(true) - -- This will break if any graphics commands are used. - local tokens = parse_ps(command) - execute_ps(tokens) - systemdict.value.stack() + end + local success, err = pcall(execute_string, tokens, context) + if not success then + if type(err) == 'table' and err.pserror then + tex.error(string.format('luapstricks: %q error occured while executing PS code from %q', err.pserror, err.context), { + string.format('The error occured while executing the PS command %q.\n%s', err.tok, err.trace) + }) + else + error(err, 0) + end + end + flush_delayed() + if not direct then + systemdict.value.grestore() + if graphics_height ~= #graphics_stack then + if graphics_height < #graphics_stack then + texio.write_nl"luapstricks: PS block contains unbalanced gsave. grestore will be executed to compensate." + repeat + systemdict.value.grestore() + until graphics_height == #graphics_stack + else + texio.write_nl"luapstricks: PS block contains unbalanced grestore." + end + end + height = TeXDict.ocount or height + local new_height = #operand_stack + assert(new_height >= height) + for k = height + 1, new_height do + operand_stack[k] = nil + end + TeXDict.ocount = saved_ocount + end end -]] local ps_tokens, ps_direct, ps_context, ps_pos_x, ps_pos_y local fid = font.define{ @@ -4151,85 +4136,56 @@ local fid = font.define{ [1] = { commands = { {'lua', function() - local tokens, direct = assert(ps_tokens), ps_direct - ps_tokens = nil - local x, y = pdf.getpos() - local TeXDict = userdict.value.TeXDict.value - local saved_ocount = TeXDict.ocount - local height = #operand_stack - TeXDict.ocount = height - operand_stack[height + 1], operand_stack[height + 2] = ps_pos_x/65781.76, ps_pos_y/65781.76 - ps_pos_x, ps_pos_y = nil - local graphics_height - if direct then - systemdict.value.moveto() - else - graphics_height = #graphics_stack - systemdict.value.gsave() - systemdict.value.translate() - end - local success, err = pcall(execute_string, tokens, ps_context) - if not success then - if type(err) == 'table' and err.pserror then - tex.error(string.format('luapstricks: %q error occured while executing PS code from %q', err.pserror, err.context), { - string.format('The error occured while executing the PS command %q.\n%s', err.tok, err.trace) - }) - else - error(err, 0) - end - end - flush_delayed() - if not direct then - systemdict.value.grestore() - if graphics_height ~= #graphics_stack then - if graphics_height < #graphics_stack then - texio.write_nl"luapstricks: PS block contains unbalanced gsave. grestore will be executed to compensate." - repeat - systemdict.value.grestore() - until graphics_height == #graphics_stack - else - texio.write_nl"luapstricks: PS block contains unbalanced grestore." - end - end - height = TeXDict.ocount or height - local new_height = #operand_stack - assert(new_height >= height) - for k = height + 1, new_height do - operand_stack[k] = nil - end - TeXDict.ocount = saved_ocount - end + local tokens, x, y = assert(ps_tokens), ps_pos_x, ps_pos_y + ps_tokens, ps_pos_x, ps_pos_y = nil + return outer_execute(tokens, ps_direct, ps_context, x, y) end} } }, }, } -local modes = tex.getmodevalues() local func = luatexbase.new_luafunction'luaPST' token.set_lua('luaPST', func, 'protected') lua.get_functions_table()[func] = function() local readstate = status.readstate or status local context = string.format('%s:%i', readstate.filename, readstate.linenumber) - local direct = token.scan_keyword'direct' + local direct = token.scan_keyword'immediate' and 'immediate' or token.scan_keyword'direct' and 'direct' + local file = token.scan_keyword'file' local tokens = token.scan_argument(true) - local n = node.new('whatsit', late_lua_sub) - setwhatsitfield(n, 'data', function(n) - assert(not ps_tokens) - ps_tokens = tokens - ps_direct = direct - ps_context = context - - local nn = node.new('glyph') - nn.subtype = 256 - nn.font, nn.char = fid, 0x1F3A8 - local list = node.new('hlist') - list.head = nn - list.direction = 0 - node.insert_after(n, n, list) - end) - node.write(n) + if file then + context = tokens + local f = io.open(kpse.find_file(tokens, 'PostScript header'), 'r') + tokens = f:read'a' + f:close() + end + if direct == 'immediate' then + local saved_pdfprint = pdfprint + pdfprint = no_pdfprint_allowed + outer_execute(tokens, direct, context) + pdfprint = saved_pdfprint + else + local n = node.new('whatsit', late_lua_sub) + setwhatsitfield(n, 'data', function(n) + assert(not ps_tokens) + ps_tokens = tokens + ps_direct = direct + ps_context = context + + local nn = node.new('glyph') + nn.subtype = 256 + nn.font, nn.char = fid, 0x1F3A8 + local list = node.new('hlist') + list.head = nn + list.direction = 0 + node.insert_after(n, n, list) + end) + node.write(n) + end end +tex.runtoks(function() + tex.sprint[[\protected\def\luaPSTheader{\luaPST direct file}]] +end) do func = luatexbase.new_luafunction'luaPSTcolor' -- cgit v1.2.3