Some backend stuff
This commit is contained in:
parent
c0954fe7f6
commit
4c0794032c
@ -11,10 +11,14 @@ local colorstacks = {{
|
|||||||
page_stack = {"0 g 0 G"},
|
page_stack = {"0 g 0 G"},
|
||||||
}}
|
}}
|
||||||
token.scan_list = token.scan_box -- They are equal if no parameter is present
|
token.scan_list = token.scan_box -- They are equal if no parameter is present
|
||||||
token.luacmd("shipout", function()
|
local function get_pfile()
|
||||||
if not pfile then
|
if not pfile then
|
||||||
pfile = newpdf.open(tex.jobname .. '.pdf')
|
pfile = newpdf.open(tex.jobname .. '.pdf')
|
||||||
end
|
end
|
||||||
|
return pfile
|
||||||
|
end
|
||||||
|
token.luacmd("shipout", function()
|
||||||
|
local pfile = get_pfile()
|
||||||
local voff = node.new'kern'
|
local voff = node.new'kern'
|
||||||
voff.kern = tex.voffset + pdf.variable.vorigin
|
voff.kern = tex.voffset + pdf.variable.vorigin
|
||||||
voff.next = token.scan_list()
|
voff.next = token.scan_list()
|
||||||
@ -30,7 +34,14 @@ token.luacmd("shipout", function()
|
|||||||
token.scan_token()
|
token.scan_token()
|
||||||
end, 'force', 'protected')
|
end, 'force', 'protected')
|
||||||
local infodir = ""
|
local infodir = ""
|
||||||
|
local catalogdir = ""
|
||||||
local creationdate = os.date("D:%Y%m%d%H%M%S%z"):gsub("+0000$", "Z"):gsub("%d%d$", "'%0")
|
local creationdate = os.date("D:%Y%m%d%H%M%S%z"):gsub("+0000$", "Z"):gsub("%d%d$", "'%0")
|
||||||
|
-- TODO: write_catalogdir is never called yet
|
||||||
|
local function write_catalogdir(p)
|
||||||
|
local additional = ""
|
||||||
|
error[[Not implemented]]
|
||||||
|
return p:indirect(nil, string.format("<<%s%s>>", catalogdir, additional))
|
||||||
|
end
|
||||||
local function write_infodir(p)
|
local function write_infodir(p)
|
||||||
local additional = ""
|
local additional = ""
|
||||||
if not string.find(infodir, "/CreationDate", 1, false) then
|
if not string.find(infodir, "/CreationDate", 1, false) then
|
||||||
@ -87,6 +98,9 @@ token.luacmd("pdfvariable", function()
|
|||||||
end)
|
end)
|
||||||
local whatsit_id = node.id'whatsit'
|
local whatsit_id = node.id'whatsit'
|
||||||
local whatsits = node.whatsits()
|
local whatsits = node.whatsits()
|
||||||
|
|
||||||
|
local lastobj = -1
|
||||||
|
|
||||||
function pdf.newcolorstack(default, mode, page)
|
function pdf.newcolorstack(default, mode, page)
|
||||||
local idx = #colorstacks
|
local idx = #colorstacks
|
||||||
colorstacks[idx + 1] = {
|
colorstacks[idx + 1] = {
|
||||||
@ -97,6 +111,9 @@ function pdf.newcolorstack(default, mode, page)
|
|||||||
}
|
}
|
||||||
return idx
|
return idx
|
||||||
end
|
end
|
||||||
|
local function do_refobj(prop, p, n, x, y)
|
||||||
|
pfile:reference(prop.obj)
|
||||||
|
end
|
||||||
local function do_literal(prop, p, n, x, y)
|
local function do_literal(prop, p, n, x, y)
|
||||||
pdf.write(prop.mode, prop.data, x, y, p)
|
pdf.write(prop.mode, prop.data, x, y, p)
|
||||||
end
|
end
|
||||||
@ -165,13 +182,15 @@ token.luacmd("pdffeedback", function()
|
|||||||
tex.sprint(tostring(pdf.newcolorstack(default, mode, page)))
|
tex.sprint(tostring(pdf.newcolorstack(default, mode, page)))
|
||||||
elseif token.scan_keyword"creationdate" then
|
elseif token.scan_keyword"creationdate" then
|
||||||
tex.sprint(creationdate)
|
tex.sprint(creationdate)
|
||||||
|
elseif token.scan_keyword"lastobj" then
|
||||||
|
tex.sprint(tostring(lastobj))
|
||||||
else
|
else
|
||||||
-- 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 feedback %s", token.scan_word()))
|
error(string.format("Unknown PDF feedback %s", token.scan_word()))
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
token.luacmd("pdfextension", function()
|
token.luacmd("pdfextension", function(_, imm)
|
||||||
if token.scan_keyword"colorstack" then
|
if token.scan_keyword"colorstack" then
|
||||||
write_colorstack()
|
write_colorstack()
|
||||||
elseif token.scan_keyword"literal" then
|
elseif token.scan_keyword"literal" then
|
||||||
@ -186,6 +205,40 @@ token.luacmd("pdfextension", function()
|
|||||||
node.write(whatsit)
|
node.write(whatsit)
|
||||||
elseif token.scan_keyword"info" then
|
elseif token.scan_keyword"info" then
|
||||||
infodir = infodir .. token.scan_string()
|
infodir = infodir .. token.scan_string()
|
||||||
|
elseif token.scan_keyword"catalog" then
|
||||||
|
catalogdir = catalogdir .. token.scan_string()
|
||||||
|
elseif token.scan_keyword"obj" then
|
||||||
|
local pfile = get_pfile()
|
||||||
|
if token.scan_keyword"reserveobjnum" then
|
||||||
|
lastobj = pfile:getobj()
|
||||||
|
else
|
||||||
|
local num = token.scan_keyword'useobjnum' and token.scan_int() or pfile:getobj()
|
||||||
|
lastobj = num
|
||||||
|
local attr = token.scan_keyword'stream' and (token.scan_keyword'attr' and token.scan_string() or '')
|
||||||
|
local isfile = token.scan_keyword'file'
|
||||||
|
local content = token.scan_string()
|
||||||
|
if immediate then
|
||||||
|
if attr then
|
||||||
|
pfile:stream(num, attr, content, isfile)
|
||||||
|
else
|
||||||
|
pfile:indirect(num, attr, content, isfile)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if attr then
|
||||||
|
pfile:delayedstream(num, attr, content, isfile)
|
||||||
|
else
|
||||||
|
pfile:delayed(num, attr, content, isfile)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif token.scan_keyword"refobj" then
|
||||||
|
local num = token.scan_int()
|
||||||
|
local whatsit = node.new(whatsit_id, whatsits.pdf_refobj)
|
||||||
|
node.setproperty(whatsit, {
|
||||||
|
obj = num,
|
||||||
|
handle = do_refobj,
|
||||||
|
})
|
||||||
|
node.write(whatsit)
|
||||||
else
|
else
|
||||||
-- 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.
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
end
|
end
|
||||||
local dimen_cmd = token.command_id'assign_dimen'
|
local dimen_cmd = token.command_id'assign_dimen'
|
||||||
local count_cmd = token.command_id'assign_int'
|
local count_cmd = token.command_id'assign_int'
|
||||||
|
local toks_cmd = token.command_id'assign_toks'
|
||||||
local tex_params = {}
|
local tex_params = {}
|
||||||
local texmeta = getmetatable(tex)
|
local texmeta = getmetatable(tex)
|
||||||
local texmetaoldindex = texmeta.__index
|
local texmetaoldindex = texmeta.__index
|
||||||
@ -20,6 +21,8 @@
|
|||||||
return tex.count[v.index]
|
return tex.count[v.index]
|
||||||
elseif v.command == dimen_cmd then
|
elseif v.command == dimen_cmd then
|
||||||
return tex.dimen[v.index]
|
return tex.dimen[v.index]
|
||||||
|
elseif v.command == toks_cmd then
|
||||||
|
return tex.toks[v.index]
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
return texmetaoldindex(t, k)
|
return texmetaoldindex(t, k)
|
||||||
@ -32,6 +35,8 @@
|
|||||||
tex.count[p.index] = v
|
tex.count[p.index] = v
|
||||||
elseif p.command == dimen_cmd then
|
elseif p.command == dimen_cmd then
|
||||||
tex.dimen[p.index] = v
|
tex.dimen[p.index] = v
|
||||||
|
elseif p.command == toks_cmd then
|
||||||
|
tex.toks[p.index] = v
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
return texmetaoldnewindex(t, k, v)
|
return texmetaoldnewindex(t, k, v)
|
||||||
@ -47,6 +52,8 @@
|
|||||||
return tex.count[v.index]
|
return tex.count[v.index]
|
||||||
elseif v.command == dimen_cmd then
|
elseif v.command == dimen_cmd then
|
||||||
return tex.dimen[v.index]
|
return tex.dimen[v.index]
|
||||||
|
elseif v.command == toks_cmd then
|
||||||
|
return tex.toks[v.index]
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
return texmetaoldindex(t, k)
|
return texmetaoldindex(t, k)
|
||||||
@ -59,6 +66,8 @@
|
|||||||
tex.count[p.index] = v
|
tex.count[p.index] = v
|
||||||
elseif p.command == dimen_cmd then
|
elseif p.command == dimen_cmd then
|
||||||
tex.dimen[p.index] = v
|
tex.dimen[p.index] = v
|
||||||
|
elseif p.command == toks_cmd then
|
||||||
|
tex.toks[p.index] = v
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
return texmetaoldnewindex(t, k, v)
|
return texmetaoldnewindex(t, k, v)
|
||||||
@ -87,10 +96,12 @@
|
|||||||
\texAlloc{dimen}{pagewidth}{210mm}
|
\texAlloc{dimen}{pagewidth}{210mm}
|
||||||
\pdfAlloc{dimen}{horigin}{1in}
|
\pdfAlloc{dimen}{horigin}{1in}
|
||||||
\pdfAlloc{dimen}{vorigin}{1in}
|
\pdfAlloc{dimen}{vorigin}{1in}
|
||||||
|
\pdfAlloc{dimen}{linkmargin}{0pt}
|
||||||
\pdfAlloc{count}{majorversion}{1}
|
\pdfAlloc{count}{majorversion}{1}
|
||||||
\pdfAlloc{count}{minorversion}{7}
|
\pdfAlloc{count}{minorversion}{7}
|
||||||
\pdfAlloc{count}{compresslevel}{0} % 0 is actually the only supported value right now, so this is basically ignored
|
\pdfAlloc{count}{compresslevel}{0} % 0 is actually the only supported value right now, so this is basically ignored
|
||||||
\pdfAlloc{count}{objcompresslevel}{0} % see above
|
\pdfAlloc{count}{objcompresslevel}{0} % see above
|
||||||
|
\pdfAlloc{toks}{pageresources}{{}}
|
||||||
|
|
||||||
\texAlloc{count}{bodydirection}{0}
|
\texAlloc{count}{bodydirection}{0}
|
||||||
\texAlloc{count}{pagedirection}{0}
|
\texAlloc{count}{pagedirection}{0}
|
||||||
|
@ -51,6 +51,7 @@ function token.luacmd(name, func, ...)
|
|||||||
return idx
|
return idx
|
||||||
end
|
end
|
||||||
local properties = node.direct.get_properties_table()
|
local properties = node.direct.get_properties_table()
|
||||||
|
node.direct.properties = properties
|
||||||
-- setmetatable(node.direct.get_properties_table(), {
|
-- setmetatable(node.direct.get_properties_table(), {
|
||||||
-- __index = function(t, id)
|
-- __index = function(t, id)
|
||||||
-- local new = {}
|
-- local new = {}
|
||||||
@ -218,3 +219,25 @@ else
|
|||||||
-- end
|
-- end
|
||||||
end
|
end
|
||||||
require'luametalatex-back-pdf'
|
require'luametalatex-back-pdf'
|
||||||
|
require'luametalatex-node-luaotfload'
|
||||||
|
|
||||||
|
local integer_code do
|
||||||
|
local value_values = token.values'value'
|
||||||
|
for i=0,#value_values do
|
||||||
|
if value_values[i] == "integer" then
|
||||||
|
integer_code = i
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
token.luacmd("Umathcodenum", function(_, scanning)
|
||||||
|
if scanning then
|
||||||
|
local class, family, char = tex.getmathcodes (token.scan_int())
|
||||||
|
return integer_code, char | (class | family << 3) << 21
|
||||||
|
else
|
||||||
|
local char = token.scan_int()
|
||||||
|
local mathcode = token.scan_int()
|
||||||
|
tex.setmathcodes(char, (mathcode >> 21) & 7, mathcode >> 24, mathcode & 0x1FFFFF)
|
||||||
|
end
|
||||||
|
end, "force", "global", "value")
|
||||||
|
|
||||||
|
@ -74,15 +74,36 @@ callback.register('open_data_file', function(name)
|
|||||||
})
|
})
|
||||||
end)
|
end)
|
||||||
callback.register('find_format_file', function(name) return kpse.find_file(name, 'fmt', true) end)
|
callback.register('find_format_file', function(name) return kpse.find_file(name, 'fmt', true) end)
|
||||||
callback.register('show_warning_message', function()
|
callback.register('handle_error_hook', function()
|
||||||
texio.write_nl('WARNING Tag: ' .. status.lastwarningtag)
|
repeat
|
||||||
texio.write_nl(status.lastwarningstring)
|
texio.write_nl'? '
|
||||||
end)
|
local line = io.read()
|
||||||
callback.register('show_error_message', function()
|
if not line then
|
||||||
if status.lasterrorcontext then
|
error[[TODO: Handle EOL]]
|
||||||
texio.write_nl('ERROR Context: ' .. status.lasterrorcontext)
|
end
|
||||||
end
|
if line == "" then return 3 end
|
||||||
texio.write_nl(status.lasterrorstring)
|
local first = line:sub(1,1):upper()
|
||||||
|
if first == 'H' then
|
||||||
|
texio.write(tex.gethelptext())
|
||||||
|
elseif first == 'I' then
|
||||||
|
line = line:sub(2)
|
||||||
|
tex.runtoks(function()
|
||||||
|
tex.sprint(token.scan_token(), line)
|
||||||
|
end)
|
||||||
|
return 3
|
||||||
|
elseif first == 'Q' then texio.write'OK, entering \\batchmode...\n' return 0
|
||||||
|
elseif first == 'R' then texio.write'OK, entering \\nonstopmode...\n' return 1
|
||||||
|
elseif first == 'S' then texio.write'OK, entering \\scrollmode...\n' return 2
|
||||||
|
elseif first == 'X' then return -1
|
||||||
|
else
|
||||||
|
texio.write'Type <return> to proceed, S to scroll future error messages,\
|
||||||
|
\z R to run without stopping, Q to run quietly,\
|
||||||
|
\z I to insert something,\
|
||||||
|
\z H for help, X to quit.'
|
||||||
|
end
|
||||||
|
until false
|
||||||
|
-- print('handle')
|
||||||
|
return 3
|
||||||
end)
|
end)
|
||||||
callback.register('pre_dump', function()
|
callback.register('pre_dump', function()
|
||||||
lua.prepared_code[1] = string.format("fixupluafunctions(%i)", fixupluafunctions())
|
lua.prepared_code[1] = string.format("fixupluafunctions(%i)", fixupluafunctions())
|
||||||
|
@ -2,12 +2,13 @@ local format = string.format
|
|||||||
local concat = table.concat
|
local concat = table.concat
|
||||||
local write = texio.write_nl
|
local write = texio.write_nl
|
||||||
local direct = node.direct
|
local direct = node.direct
|
||||||
local properties = direct.get_properties_table()
|
local properties = direct.properties
|
||||||
local tonode = direct.tonode
|
local tonode = direct.tonode
|
||||||
local todirect = direct.todirect
|
local todirect = direct.todirect
|
||||||
local getid = direct.getid
|
local getid = direct.getid
|
||||||
local traverse = direct.traverse
|
local traverse = direct.traverse
|
||||||
local getsubtype = direct.getsubtype
|
local getsubtype = direct.getsubtype
|
||||||
|
local getdirection = direct.getdirection
|
||||||
local setsubtype = direct.setsubtype
|
local setsubtype = direct.setsubtype
|
||||||
local getdepth = direct.getdepth
|
local getdepth = direct.getdepth
|
||||||
local getheight = direct.getheight
|
local getheight = direct.getheight
|
||||||
@ -27,6 +28,10 @@ local getnext = direct.getnext
|
|||||||
local getexpansion = direct.getexpansion
|
local getexpansion = direct.getexpansion
|
||||||
local getchar = direct.getchar
|
local getchar = direct.getchar
|
||||||
local rangedimensions = direct.rangedimensions
|
local rangedimensions = direct.rangedimensions
|
||||||
|
local traverse_id = direct.traverse_id
|
||||||
|
|
||||||
|
local dir_id = node.id'dir'
|
||||||
|
|
||||||
local function doublekeyed(t, id2name, name2id, index)
|
local function doublekeyed(t, id2name, name2id, index)
|
||||||
return setmetatable(t, {
|
return setmetatable(t, {
|
||||||
__index = index,
|
__index = index,
|
||||||
@ -42,7 +47,8 @@ local function doublekeyed(t, id2name, name2id, index)
|
|||||||
end
|
end
|
||||||
local nodehandler = (function()
|
local nodehandler = (function()
|
||||||
local function unknown_handler(_, n, x, y)
|
local function unknown_handler(_, n, x, y)
|
||||||
write(format("Sorry, but the PDF backend does not support %q (id = %i) nodes right now. The supplied node will be dropped at coordinates (%i, %i).", node.type(getid(n)), getid(n), x, y))
|
print(node.type(10))
|
||||||
|
write(format("Sorry, but the PDF backend does not support %q (id = %i) nodes right now. The supplied node will be dropped at coordinates (%i, %i).", node.type(getid(n)), getid(n), x//1, y//1))
|
||||||
end
|
end
|
||||||
return doublekeyed({}, node.type, node.id, function()
|
return doublekeyed({}, node.type, node.id, function()
|
||||||
return unknown_handler
|
return unknown_handler
|
||||||
@ -55,7 +61,7 @@ local whatsithandler = (function()
|
|||||||
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
|
||||||
write(format("Sorry, but the PDF backend does not support %q (id = %i) whatsits right now. The supplied node will be dropped at coordinates (%i, %i).", whatsits[getsubtype(n)], getsubtype(n), x, y))
|
write(format("Sorry, but the PDF backend does not support %q (id = %i) whatsits right now. The supplied node will be dropped at coordinates (%i, %i).", whatsits[getsubtype(n)], getsubtype(n), x//1, y//1))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return doublekeyed({}, function(n)return whatsits[n]end, function(n)return whatsits[n]end, function()
|
return doublekeyed({}, function(n)return whatsits[n]end, function(n)return whatsits[n]end, function()
|
||||||
@ -185,9 +191,10 @@ local function write_link(p, link)
|
|||||||
for i=1,#quads do quads[i] = nil end
|
for i=1,#quads do quads[i] = nil end
|
||||||
link.objnum = nil
|
link.objnum = nil
|
||||||
end
|
end
|
||||||
local function addlinkpoint(p, link, x, y, list, final)
|
local function addlinkpoint(p, link, x, y, list, kind)
|
||||||
local quads = link.quads
|
local quads = link.quads
|
||||||
print'addlink'
|
local off = pdf.variable.linkmargin
|
||||||
|
x = kind == 'start' and x-off or x+off
|
||||||
if link.annots and link.annots ~= p.annots then -- We started on another page, let's finish that before starting the new page
|
if link.annots and link.annots ~= p.annots then -- We started on another page, let's finish that before starting the new page
|
||||||
write_link(p, link)
|
write_link(p, link)
|
||||||
link.annots = nil
|
link.annots = nil
|
||||||
@ -198,12 +205,12 @@ local function addlinkpoint(p, link, x, y, list, final)
|
|||||||
p.annots[#p.annots+1] = link.objnum .. " 0 R"
|
p.annots[#p.annots+1] = link.objnum .. " 0 R"
|
||||||
end
|
end
|
||||||
local m = p.matrix
|
local m = p.matrix
|
||||||
local lx, ly = projected_point(m, x, y-(link.depth or getdepth(list)))
|
local lx, ly = projected_point(m, x, y-off-(link.depth or getdepth(list)))
|
||||||
local ux, uy = projected_point(m, x, y+(link.height or getheight(list)))
|
local ux, uy = projected_point(m, x, y+off+(link.height or getheight(list)))
|
||||||
local n = #quads
|
local n = #quads
|
||||||
quads[n+1], quads[n+2], quads[n+3], quads[n+4] = lx, ly, ux, uy
|
quads[n+1], quads[n+2], quads[n+3], quads[n+4] = lx, ly, ux, uy
|
||||||
if final or (link.force_separate and (n+4)%8 == 0) then
|
if kind == 'final' or (link.force_separate and (n+4)%8 == 0) then
|
||||||
print(final, n, link.force_separate)
|
print(kind, n, link.force_separate)
|
||||||
write_link(p, link)
|
write_link(p, link)
|
||||||
link.annots = nil
|
link.annots = nil
|
||||||
end
|
end
|
||||||
@ -216,18 +223,56 @@ function nodehandler.hlist(p, list, x0, y, outerlist, origin, level)
|
|||||||
x0 = x0 + getshift(list)
|
x0 = x0 + getshift(list)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
local direction = getdirection(list)
|
||||||
|
if direction == 1 then
|
||||||
|
x0 = x0 + getwidth(list)
|
||||||
|
end
|
||||||
|
local dirstack = {}
|
||||||
|
local dirnodes = {}
|
||||||
|
for n, sub in traverse_id(dir_id, getlist(list)) do
|
||||||
|
if sub == 0 then
|
||||||
|
dirstack[#dirstack + 1] = n
|
||||||
|
else
|
||||||
|
local m = dirstack[#dirstack]
|
||||||
|
dirnodes[m] = n
|
||||||
|
dirstack[#dirstack] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for i=1,#dirstack do
|
||||||
|
dirnodes[dirstack[i]] = rangedimensions(list, dirstack[i])
|
||||||
|
end
|
||||||
local x = x0
|
local x = x0
|
||||||
for _,l in ipairs(p.linkcontext) do if l.level == level+1 then
|
for _,l in ipairs(p.linkcontext) do if l.level == level+1 then
|
||||||
addlinkpoint(p, l, x, y, list)
|
addlinkpoint(p, l, x, y, list, 'start')
|
||||||
end end
|
end end
|
||||||
for n in traverse(getlist(list)) do
|
for n, id, sub in traverse(getlist(list)) do
|
||||||
local next = getnext(n)
|
if id == dir_id then
|
||||||
local w = next and rangedimensions(list, n, next) or rangedimensions(list, n)
|
if sub == 0 then
|
||||||
nodehandler[getid(n)](p, n, x, y, list, x0, level+1)
|
local newdir = getdirection(n)
|
||||||
x = w + x
|
if newdir ~= direction then
|
||||||
|
local close = dirnodes[n]
|
||||||
|
local dim = rangedimensions(list, n, close)
|
||||||
|
if close then dirnodes[close] = dim end
|
||||||
|
x = x + (2*newdir-1) * dim
|
||||||
|
direction = newdir
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local dim = dirnodes[n]
|
||||||
|
if dim then
|
||||||
|
direction = 1-direction
|
||||||
|
x = x + (2*newdir-1) * dim
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local next = getnext(n)
|
||||||
|
local w = next and rangedimensions(list, n, next) or rangedimensions(list, n)
|
||||||
|
if direction == 1 then x = x - w end
|
||||||
|
nodehandler[id](p, n, x, y, list, x0, level+1)
|
||||||
|
if direction == 0 then x = w + x end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
for _,l in ipairs(p.linkcontext) do if l.level == level+1 then
|
for _,l in ipairs(p.linkcontext) do if l.level == level+1 then
|
||||||
addlinkpoint(p, l, x, y, list)
|
addlinkpoint(p, l, x, y, list, 'end')
|
||||||
end end
|
end end
|
||||||
end
|
end
|
||||||
function nodehandler.vlist(p, list, x, y0, outerlist, origin, level)
|
function nodehandler.vlist(p, list, x, y0, outerlist, origin, level)
|
||||||
@ -484,14 +529,14 @@ function whatsithandler.pdf_start_link(p, n, x, y, outer, _, level)
|
|||||||
local links = p.linkcontext
|
local links = p.linkcontext
|
||||||
local link = {quads = {}, attr = n.link_attr, action = n.action, level = level, force_separate = false} -- force_separate should become an option
|
local link = {quads = {}, attr = n.link_attr, action = n.action, level = level, force_separate = false} -- force_separate should become an option
|
||||||
links[#links+1] = link
|
links[#links+1] = link
|
||||||
addlinkpoint(p, link, x, y, outer)
|
addlinkpoint(p, link, x, y, outer, 'start')
|
||||||
end
|
end
|
||||||
function whatsithandler.pdf_end_link(p, n, x, y, outer, _, level)
|
function whatsithandler.pdf_end_link(p, n, x, y, outer, _, level)
|
||||||
local links = p.linkcontext
|
local links = p.linkcontext
|
||||||
local link = links[#links]
|
local link = links[#links]
|
||||||
links[#links] = nil
|
links[#links] = nil
|
||||||
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, 'final')
|
||||||
end
|
end
|
||||||
]]
|
]]
|
||||||
local global_p, global_x, global_y
|
local global_p, global_x, global_y
|
||||||
|
@ -6,28 +6,69 @@ local error = error
|
|||||||
local pairs = pairs
|
local pairs = pairs
|
||||||
local setmetatable = setmetatable
|
local setmetatable = setmetatable
|
||||||
local assigned = {}
|
local assigned = {}
|
||||||
local function stream(pdf, num, dict, content)
|
local delayed = {}
|
||||||
|
local function stream(pdf, num, dict, content, isfile)
|
||||||
if not num then num = pdf:getobj() end
|
if not num then num = pdf:getobj() end
|
||||||
if pdf[num] ~= assigned then
|
if pdf[num] ~= assigned then
|
||||||
error[[Invalid object]]
|
error[[Invalid object]]
|
||||||
end
|
end
|
||||||
pdf[num] = {offset = pdf.file:seek()}
|
pdf[num] = {offset = pdf.file:seek()}
|
||||||
|
if isfile then
|
||||||
|
local f = io.open(content)
|
||||||
|
content = f:read'a'
|
||||||
|
f:close()
|
||||||
|
end
|
||||||
pdf.file:write(format('%i 0 obj\n<<%s/Length %i>>stream\n', num, dict, #content))
|
pdf.file:write(format('%i 0 obj\n<<%s/Length %i>>stream\n', num, dict, #content))
|
||||||
pdf.file:write(content)
|
pdf.file:write(content)
|
||||||
pdf.file:write'\nendstream\nendobj\n'
|
pdf.file:write'\nendstream\nendobj\n'
|
||||||
return num
|
return num
|
||||||
end
|
end
|
||||||
local function indirect(pdf, num, content)
|
local function delayedstream(pdf, num, dict, content, isfile)
|
||||||
|
if not num then num = pdf:getobj() end
|
||||||
|
if pdf[num] ~= assigned then
|
||||||
|
error[[Invalid object]]
|
||||||
|
end
|
||||||
|
pdf[num] = delayed
|
||||||
|
pdf[-num] = {stream, dict, content, isfile}
|
||||||
|
return num
|
||||||
|
end
|
||||||
|
local function indirect(pdf, num, content, isfile)
|
||||||
if not num then num = pdf:getobj() end
|
if not num then num = pdf:getobj() end
|
||||||
if pdf[num] ~= assigned then
|
if pdf[num] ~= assigned then
|
||||||
error[[Invalid object]]
|
error[[Invalid object]]
|
||||||
end
|
end
|
||||||
pdf[num] = {offset = pdf.file:seek()}
|
pdf[num] = {offset = pdf.file:seek()}
|
||||||
pdf.file:write(format('%i 0 obj\n', num))
|
pdf.file:write(format('%i 0 obj\n', num))
|
||||||
|
if isfile then
|
||||||
|
local f = io.open(content)
|
||||||
|
content = f:read'a'
|
||||||
|
f:close()
|
||||||
|
end
|
||||||
pdf.file:write(content)
|
pdf.file:write(content)
|
||||||
pdf.file:write'\nendobj\n'
|
pdf.file:write'\nendobj\n'
|
||||||
return num
|
return num
|
||||||
end
|
end
|
||||||
|
local function delayed(pdf, num, content, isfile)
|
||||||
|
if not num then num = pdf:getobj() end
|
||||||
|
if pdf[num] ~= assigned then
|
||||||
|
error[[Invalid object]]
|
||||||
|
end
|
||||||
|
pdf[num] = delayed
|
||||||
|
pdf[-num] = {indirect, content, isfile}
|
||||||
|
return num
|
||||||
|
end
|
||||||
|
local function reference(pdf, num)
|
||||||
|
local status = pdf[num]
|
||||||
|
if status == delayed then
|
||||||
|
local saved = pdf[-num]
|
||||||
|
pdf[-num] = nil
|
||||||
|
pdf[num] = assigned
|
||||||
|
return saved[1](pdf, num, table.unpack(saved, 2))
|
||||||
|
elseif status == assigned or not status then
|
||||||
|
error[[Invalid object]]
|
||||||
|
-- else -- Already written
|
||||||
|
end
|
||||||
|
end
|
||||||
local function getid(pdf)
|
local function getid(pdf)
|
||||||
local id = pdf[0] + 1
|
local id = pdf[0] + 1
|
||||||
pdf[0] = id
|
pdf[0] = id
|
||||||
@ -73,9 +114,9 @@ local pdfmeta = {
|
|||||||
stream = stream,
|
stream = stream,
|
||||||
newpage = pagetree.newpage,
|
newpage = pagetree.newpage,
|
||||||
writepages = pagetree.write,
|
writepages = pagetree.write,
|
||||||
-- delayed = delayed,
|
delayed = delayed,
|
||||||
-- delayedstream = delayedstream,
|
delayedstream = delayedstream,
|
||||||
-- reference
|
reference = reference,
|
||||||
}
|
}
|
||||||
pdfmeta.__index = pdfmeta
|
pdfmeta.__index = pdfmeta
|
||||||
local function open(filename)
|
local function open(filename)
|
||||||
|
Loading…
Reference in New Issue
Block a user