Bugfixes, Color stack support, pdf.write, ...
This commit is contained in:
parent
fcbad724ed
commit
3aacd0fddb
@ -1,8 +1,15 @@
|
|||||||
|
local pdf = pdf
|
||||||
local writer = require'luametalatex-nodewriter'
|
local writer = require'luametalatex-nodewriter'
|
||||||
local newpdf = require'luametalatex-pdf'
|
local newpdf = require'luametalatex-pdf'
|
||||||
local pfile = newpdf.open(tex.jobname .. '.pdf')
|
local pfile = newpdf.open(tex.jobname .. '.pdf')
|
||||||
local fontdirs = setmetatable({}, {__index=function(t, k)t[k] = pfile:getobj() return t[k] end})
|
local fontdirs = setmetatable({}, {__index=function(t, k)t[k] = pfile:getobj() return t[k] end})
|
||||||
local usedglyphs = {}
|
local usedglyphs = {}
|
||||||
|
local colorstacks = {{
|
||||||
|
page = true,
|
||||||
|
mode = "direct",
|
||||||
|
default = "0 g 0 G",
|
||||||
|
page_stack = {"0 g 0 G"},
|
||||||
|
}}
|
||||||
token.luacmd("shipout", function()
|
token.luacmd("shipout", function()
|
||||||
local voff = node.new'kern'
|
local voff = node.new'kern'
|
||||||
voff.kern = tex.voffset + pdf.variable.vorigin
|
voff.kern = tex.voffset + pdf.variable.vorigin
|
||||||
@ -11,7 +18,7 @@ token.luacmd("shipout", function()
|
|||||||
local list = node.vpack(voff)
|
local list = node.vpack(voff)
|
||||||
list.height = tex.pageheight
|
list.height = tex.pageheight
|
||||||
list.width = tex.pagewidth
|
list.width = tex.pagewidth
|
||||||
local out, resources, annots = writer(pfile, list, fontdirs, usedglyphs)
|
local out, resources, annots = writer(pfile, list, fontdirs, usedglyphs, colorstacks)
|
||||||
local page, parent = pfile:newpage()
|
local page, parent = pfile:newpage()
|
||||||
local content = pfile:stream(nil, '', out)
|
local content = pfile:stream(nil, '', out)
|
||||||
pfile:indirect(page, string.format([[<</Type/Page/Parent %i 0 R/Contents %i 0 R/MediaBox[0 %i %i %i]/Resources%s%s>>]], parent, content, -math.ceil(list.depth/65781.76), math.ceil(list.width/65781.76), math.ceil(list.height/65781.76), resources, annots))
|
pfile:indirect(page, string.format([[<</Type/Page/Parent %i 0 R/Contents %i 0 R/MediaBox[0 %i %i %i]/Resources%s%s>>]], parent, content, -math.ceil(list.depth/65781.76), math.ceil(list.width/65781.76), math.ceil(list.height/65781.76), resources, annots))
|
||||||
@ -42,5 +49,89 @@ token.luacmd("pdfvariable", function()
|
|||||||
end
|
end
|
||||||
-- The following error message gobbles the next word as a side effect.
|
-- The following error message gobbles the next word as a side effect.
|
||||||
-- This is intentional to make error-recovery easier.
|
-- This is intentional to make error-recovery easier.
|
||||||
error(string.format("Unknown PDF variable %s", token.scan_string()))
|
error(string.format("Unknown PDF variable %s", token.scan_word()))
|
||||||
|
end)
|
||||||
|
local whatsit_id = node.id'whatsit'
|
||||||
|
local whatsits = node.whatsits()
|
||||||
|
function pdf.newcolorstack(default, mode, page)
|
||||||
|
local idx = #colorstacks
|
||||||
|
colorstacks[idx + 1] = {
|
||||||
|
page = page,
|
||||||
|
mode = mode or "origin",
|
||||||
|
default = default,
|
||||||
|
page_stack = {default},
|
||||||
|
}
|
||||||
|
return idx
|
||||||
|
end
|
||||||
|
local function do_colorstack(prop, p, n, x, y)
|
||||||
|
local colorstack = prop.colorstack
|
||||||
|
local stack
|
||||||
|
if p.is_page then
|
||||||
|
stack = colorstack.page_stack
|
||||||
|
elseif prop.last_form == resources then
|
||||||
|
stack = colorstack.form_stack
|
||||||
|
else
|
||||||
|
stack = {prop.default}
|
||||||
|
colorstack.form_stack = stack
|
||||||
|
end
|
||||||
|
if prop.action == "push" then
|
||||||
|
stack[#stack+1] = prop.data
|
||||||
|
elseif prop.action == "pop" then
|
||||||
|
assert(#stack > 1)
|
||||||
|
stack[#stack] = nil
|
||||||
|
elseif prop.action == "set" then
|
||||||
|
stack[#stack] = prop.data
|
||||||
|
end
|
||||||
|
pdf.write(colorstack.mode, stack[#stack], x, y, p)
|
||||||
|
end
|
||||||
|
local function write_colorstack()
|
||||||
|
local idx = token.scan_int()
|
||||||
|
local colorstack = colorstacks[idx + 1]
|
||||||
|
if not colorstack then
|
||||||
|
error[[Undefined colorstack]]
|
||||||
|
end
|
||||||
|
local action = token.scan_keyword'pop' and 'pop'
|
||||||
|
or token.scan_keyword'set' and 'set'
|
||||||
|
or token.scan_keyword'current' and 'current'
|
||||||
|
or token.scan_keyword'push' and 'push'
|
||||||
|
if not action then
|
||||||
|
error[[Missing action specifier for colorstack command]]
|
||||||
|
end
|
||||||
|
local text
|
||||||
|
if action == "push" or "set" then
|
||||||
|
text = token.scan_string()
|
||||||
|
-- text = token.to_string(token.scan_tokenlist()) -- Attention! This should never be executed in an expand-only context
|
||||||
|
end
|
||||||
|
local whatsit = node.new(whatsit_id, whatsits.pdf_colorstack)
|
||||||
|
node.setproperty(whatsit, {
|
||||||
|
handle = do_colorstack,
|
||||||
|
colorstack = colorstack,
|
||||||
|
action = action,
|
||||||
|
data = text,
|
||||||
|
})
|
||||||
|
node.write(whatsit)
|
||||||
|
end
|
||||||
|
token.luacmd("pdffeedback", function()
|
||||||
|
if token.scan_keyword"colorstackinit" then
|
||||||
|
local page = token.scan_keyword'page'
|
||||||
|
or (token.scan_keyword'nopage' and false) -- If you want to pass "page" as mode
|
||||||
|
local mode = token.scan_keyword'direct' and 'direct'
|
||||||
|
or token.scan_keyword'page' and 'page'
|
||||||
|
or 'origin'
|
||||||
|
local default = token.scan_string()
|
||||||
|
tex.sprint(tostring(pdf.newcolorstack(default, mode, page)))
|
||||||
|
else
|
||||||
|
-- The following error message gobbles the next word as a side effect.
|
||||||
|
-- This is intentional to make error-recovery easier.
|
||||||
|
error(string.format("Unknown PDF feedback %s", token.scan_word()))
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
token.luacmd("pdfextension", function()
|
||||||
|
if token.scan_keyword"colorstack" then
|
||||||
|
write_colorstack()
|
||||||
|
else
|
||||||
|
-- The following error message gobbles the next word as a side effect.
|
||||||
|
-- This is intentional to make error-recovery easier.
|
||||||
|
error(string.format("Unknown PDF extension %s", token.scan_word()))
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
|
@ -314,7 +314,13 @@ end
|
|||||||
--
|
--
|
||||||
-- unicode = {utf8 = utf8}
|
-- unicode = {utf8 = utf8}
|
||||||
-- utf8.byte = utf8.codepoint
|
-- utf8.byte = utf8.codepoint
|
||||||
kpse.set_program_name()
|
do
|
||||||
|
local progname
|
||||||
|
for _, a in ipairs(arg) do if a:sub(1,11) == "--progname=" then
|
||||||
|
progname = a:sub(12)
|
||||||
|
end end
|
||||||
|
kpse.set_program_name(nil, progname)
|
||||||
|
end
|
||||||
package.searchers[2] = function(modname)
|
package.searchers[2] = function(modname)
|
||||||
local filename = kpse.find_file(modname, "kpse_lua_format", true)
|
local filename = kpse.find_file(modname, "kpse_lua_format", true)
|
||||||
if not filename then
|
if not filename then
|
||||||
|
@ -26,7 +26,7 @@ end)()
|
|||||||
local whatsithandler = (function()
|
local whatsithandler = (function()
|
||||||
local whatsits = node.whatsits()
|
local whatsits = node.whatsits()
|
||||||
local function unknown_handler(p, n, x, y, ...)
|
local function unknown_handler(p, n, x, y, ...)
|
||||||
local prop = properties[n]
|
local prop = properties[n] or node.getproperty(n)
|
||||||
if prop and prop.handle then
|
if prop and prop.handle then
|
||||||
prop:handle(p, n, x, y, ...)
|
prop:handle(p, n, x, y, ...)
|
||||||
else
|
else
|
||||||
@ -398,7 +398,8 @@ function nodehandler.glyph(p, n, x, y, ...)
|
|||||||
local f, fid = p.vfont.font, p.vfont.fid
|
local f, fid = p.vfont.font, p.vfont.fid
|
||||||
local c = f.characters[n.char]
|
local c = f.characters[n.char]
|
||||||
if not c then
|
if not c then
|
||||||
error[[Invalid characters]]
|
texio.write_nl("Missing character")
|
||||||
|
return
|
||||||
end
|
end
|
||||||
if c.commands then return do_commands(p, c, f, fid, x, y, ...) end
|
if c.commands then return do_commands(p, c, f, fid, x, y, ...) end
|
||||||
toglyph(p, n.font, x + n.xoffset, y + n.yoffset, n.expansion_factor)
|
toglyph(p, n.font, x + n.xoffset, y + n.yoffset, n.expansion_factor)
|
||||||
@ -473,6 +474,25 @@ function whatsithandler.pdf_end_link(p, n, x, y, outer, _, level)
|
|||||||
if link.level ~= level then error[[Wrong link level]] end
|
if link.level ~= level then error[[Wrong link level]] end
|
||||||
addlinkpoint(p, link, x, y, outer, true)
|
addlinkpoint(p, link, x, y, outer, true)
|
||||||
end
|
end
|
||||||
|
local global_p, global_x, global_y
|
||||||
|
function pdf._latelua(p, x, y, func, ...)
|
||||||
|
global_p, global_x, global_y = p, x, y
|
||||||
|
return func(...)
|
||||||
|
end
|
||||||
|
function pdf.write(mode, text, x, y, p)
|
||||||
|
x, y, p = x or global_x, y or global_y, p or global_p
|
||||||
|
if mode == "direct" then
|
||||||
|
topage(p)
|
||||||
|
p.strings[#p.strings + 1] = text
|
||||||
|
elseif mode == "origin" then
|
||||||
|
write_matrix(p, 1, 0, 0, 1, x, y)
|
||||||
|
topage(p)
|
||||||
|
p.strings[#p.strings + 1] = text
|
||||||
|
write_matrix(p, 1, 0, 0, 1, -x, -y)
|
||||||
|
else
|
||||||
|
write(format('Literal type %s unsupported', mode))
|
||||||
|
end
|
||||||
|
end
|
||||||
local ondemandmeta = {
|
local ondemandmeta = {
|
||||||
__index = function(t, k)
|
__index = function(t, k)
|
||||||
t[k] = {}
|
t[k] = {}
|
||||||
@ -494,7 +514,7 @@ local function writeresources(p)
|
|||||||
return concat(result)
|
return concat(result)
|
||||||
end
|
end
|
||||||
local fontnames = setmetatable({}, {__index = function(t, k) local res = format("F%i", k) t[k] = res return res end})
|
local fontnames = setmetatable({}, {__index = function(t, k) local res = format("F%i", k) t[k] = res return res end})
|
||||||
return function(file, n, fontdirs, usedglyphs)
|
return function(file, n, fontdirs, usedglyphs, colorstacks)
|
||||||
setmetatable(usedglyphs, ondemandmeta)
|
setmetatable(usedglyphs, ondemandmeta)
|
||||||
local linkcontext = file.linkcontext
|
local linkcontext = file.linkcontext
|
||||||
if not linkcontext then
|
if not linkcontext then
|
||||||
@ -502,6 +522,7 @@ return function(file, n, fontdirs, usedglyphs)
|
|||||||
file.linkcontext = linkcontext
|
file.linkcontext = linkcontext
|
||||||
end
|
end
|
||||||
local p = {
|
local p = {
|
||||||
|
is_page = not not colorstacks,
|
||||||
file = file,
|
file = file,
|
||||||
mode = 3,
|
mode = 3,
|
||||||
strings = {},
|
strings = {},
|
||||||
@ -521,6 +542,17 @@ return function(file, n, fontdirs, usedglyphs)
|
|||||||
annots = {},
|
annots = {},
|
||||||
linkcontext = file.linkcontext,
|
linkcontext = file.linkcontext,
|
||||||
}
|
}
|
||||||
|
if colorstacks then
|
||||||
|
for i=1, #colorstacks do
|
||||||
|
local colorstack = colorstacks[i]
|
||||||
|
if colorstack.page then
|
||||||
|
local stack = colorstack.page_stack
|
||||||
|
if colorstack.default ~= stack[#stack] then
|
||||||
|
pdf.write(colorstack.mode, stack[#stack], 0, 0, p)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
nodehandler[n.id](p, n, 0, 0, n, nil, 0)
|
nodehandler[n.id](p, n, 0, 0, n, nil, 0)
|
||||||
-- nodehandler[n.id](p, n, 0, n.depth, n)
|
-- nodehandler[n.id](p, n, 0, n.depth, n)
|
||||||
topage(p)
|
topage(p)
|
||||||
|
Loading…
Reference in New Issue
Block a user