Work on catalog and dests
This commit is contained in:
parent
4c0794032c
commit
f20e543cce
@ -4,6 +4,8 @@ local newpdf = require'luametalatex-pdf'
|
|||||||
local pfile
|
local pfile
|
||||||
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 dests = {}
|
||||||
|
local cur_page
|
||||||
local colorstacks = {{
|
local colorstacks = {{
|
||||||
page = true,
|
page = true,
|
||||||
mode = "direct",
|
mode = "direct",
|
||||||
@ -11,12 +13,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
|
||||||
|
local spacer_cmd = token.command_id'spacer'
|
||||||
local function get_pfile()
|
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
|
return pfile
|
||||||
end
|
end
|
||||||
|
local properties = node.direct.properties
|
||||||
token.luacmd("shipout", function()
|
token.luacmd("shipout", function()
|
||||||
local pfile = get_pfile()
|
local pfile = get_pfile()
|
||||||
local voff = node.new'kern'
|
local voff = node.new'kern'
|
||||||
@ -26,8 +30,10 @@ token.luacmd("shipout", function()
|
|||||||
local list = node.direct.tonode(node.direct.vpack(node.direct.todirect(voff)))
|
local list = node.direct.tonode(node.direct.vpack(node.direct.todirect(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, colorstacks)
|
|
||||||
local page, parent = pfile:newpage()
|
local page, parent = pfile:newpage()
|
||||||
|
cur_page = page
|
||||||
|
local out, resources, annots = writer(pfile, list, fontdirs, usedglyphs, colorstacks)
|
||||||
|
cur_page = nil
|
||||||
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))
|
||||||
token.put_next(token.create'immediateassignment', token.create'global', token.create'deadcycles', token.create(0x30), token.create'relax')
|
token.put_next(token.create'immediateassignment', token.create'global', token.create'deadcycles', token.create(0x30), token.create'relax')
|
||||||
@ -36,12 +42,6 @@ end, 'force', 'protected')
|
|||||||
local infodir = ""
|
local infodir = ""
|
||||||
local catalogdir = ""
|
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
|
||||||
@ -77,7 +77,7 @@ callback.register("stop_run", function()
|
|||||||
end
|
end
|
||||||
pfile.root = pfile:getobj()
|
pfile.root = pfile:getobj()
|
||||||
pfile.version = string.format("%i.%i", pdf.variable.majorversion, pdf.variable.minorversion)
|
pfile.version = string.format("%i.%i", pdf.variable.majorversion, pdf.variable.minorversion)
|
||||||
pfile:indirect(pfile.root, string.format([[<</Type/Catalog/Version/%s/Pages %i 0 R>>]], pfile.version, pfile:writepages()))
|
pfile:indirect(pfile.root, string.format([[<</Type/Catalog/Version/%s/Pages %i 0 R%s>>]], pfile.version, pfile:writepages(), catalogdir))
|
||||||
pfile.info = write_infodir(pfile)
|
pfile.info = write_infodir(pfile)
|
||||||
pfile:close()
|
pfile:close()
|
||||||
end, "Finish PDF file")
|
end, "Finish PDF file")
|
||||||
@ -111,6 +111,39 @@ function pdf.newcolorstack(default, mode, page)
|
|||||||
}
|
}
|
||||||
return idx
|
return idx
|
||||||
end
|
end
|
||||||
|
local function sp2bp(sp)
|
||||||
|
return sp/65781.76
|
||||||
|
end
|
||||||
|
local function do_dest(prop, p, n, x, y)
|
||||||
|
-- TODO: Apply matrix
|
||||||
|
assert(cur_page, "Destinations can not appear outside of a page")
|
||||||
|
local id = prop.dest_id
|
||||||
|
local dest_type = prop.dest_type
|
||||||
|
local data
|
||||||
|
if dest_type == "xyz" then
|
||||||
|
local zoom = prop.xyz_zoom
|
||||||
|
if zoom then
|
||||||
|
data = string.format("[%i 0 R/XYZ %.5f %.5f %.3f]", cur_page, sp2bp(x), sp2bp(y), prop.zoom/1000)
|
||||||
|
else
|
||||||
|
data = string.format("[%i 0 R/XYZ %.5f %.5f null]", cur_page, sp2bp(x), sp2bp(y))
|
||||||
|
end
|
||||||
|
elseif dest_type == "fitr" then
|
||||||
|
data = string.format("[%i 0 R/FitR %.5f %.5f %.5f %.5f]", cur_page, sp2bp(x), sp2bp(y + prop.depth), sp2bp(x + prop.width), sp2bp(y - prop.height))
|
||||||
|
elseif dest_type == "fit" then
|
||||||
|
data = string.format("[%i 0 R/Fit]", cur_page)
|
||||||
|
elseif dest_type == "fith" then
|
||||||
|
data = string.format("[%i 0 R/FitH %.5f]", cur_page, sp2bp(y))
|
||||||
|
elseif dest_type == "fitv" then
|
||||||
|
data = string.format("[%i 0 R/FitV %.5f]", cur_page, sp2bp(x))
|
||||||
|
elseif dest_type == "fitb" then
|
||||||
|
data = string.format("[%i 0 R/FitB]", cur_page)
|
||||||
|
elseif dest_type == "fitbh" then
|
||||||
|
data = string.format("[%i 0 R/FitBH %.5f]", cur_page, sp2bp(y))
|
||||||
|
elseif dest_type == "fitbv" then
|
||||||
|
data = string.format("[%i 0 R/FitBV %.5f]", cur_page, sp2bp(x))
|
||||||
|
end
|
||||||
|
dests[id] = pfile:indirect(dests[id], data)
|
||||||
|
end
|
||||||
local function do_refobj(prop, p, n, x, y)
|
local function do_refobj(prop, p, n, x, y)
|
||||||
pfile:reference(prop.obj)
|
pfile:reference(prop.obj)
|
||||||
end
|
end
|
||||||
@ -173,6 +206,12 @@ local function scan_literal_mode()
|
|||||||
or token.scan_keyword"raw" and "raw"
|
or token.scan_keyword"raw" and "raw"
|
||||||
or "origin"
|
or "origin"
|
||||||
end
|
end
|
||||||
|
local function maybe_gobble_cmd(cmd)
|
||||||
|
local t = token.scan_token()
|
||||||
|
if t.command ~= cmd then
|
||||||
|
token.put_next(cmd)
|
||||||
|
end
|
||||||
|
end
|
||||||
token.luacmd("pdffeedback", function()
|
token.luacmd("pdffeedback", function()
|
||||||
if token.scan_keyword"colorstackinit" then
|
if token.scan_keyword"colorstackinit" then
|
||||||
local page = token.scan_keyword'page'
|
local page = token.scan_keyword'page'
|
||||||
@ -206,7 +245,7 @@ token.luacmd("pdfextension", function(_, imm)
|
|||||||
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
|
elseif token.scan_keyword"catalog" then
|
||||||
catalogdir = catalogdir .. token.scan_string()
|
catalogdir = catalogdir .. ' ' .. token.scan_string()
|
||||||
elseif token.scan_keyword"obj" then
|
elseif token.scan_keyword"obj" then
|
||||||
local pfile = get_pfile()
|
local pfile = get_pfile()
|
||||||
if token.scan_keyword"reserveobjnum" then
|
if token.scan_keyword"reserveobjnum" then
|
||||||
@ -221,7 +260,7 @@ token.luacmd("pdfextension", function(_, imm)
|
|||||||
if attr then
|
if attr then
|
||||||
pfile:stream(num, attr, content, isfile)
|
pfile:stream(num, attr, content, isfile)
|
||||||
else
|
else
|
||||||
pfile:indirect(num, attr, content, isfile)
|
pfile:indirect(num, content, isfile)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if attr then
|
if attr then
|
||||||
@ -239,6 +278,64 @@ token.luacmd("pdfextension", function(_, imm)
|
|||||||
handle = do_refobj,
|
handle = do_refobj,
|
||||||
})
|
})
|
||||||
node.write(whatsit)
|
node.write(whatsit)
|
||||||
|
elseif token.scan_keyword"dest" then
|
||||||
|
local id
|
||||||
|
if token.scan_keyword'num' then
|
||||||
|
id = token.scan_int()
|
||||||
|
if not id > 0 then
|
||||||
|
error[[id must be positive]]
|
||||||
|
end
|
||||||
|
elseif token.scan_keyword'name' then
|
||||||
|
id = token.scan_string()
|
||||||
|
else
|
||||||
|
error[[Unsupported id type]]
|
||||||
|
end
|
||||||
|
local whatsit = node.new(whatsit_id, whatsits.pdf_dest)
|
||||||
|
local prop = {
|
||||||
|
dest_id = id,
|
||||||
|
handle = do_dest,
|
||||||
|
}
|
||||||
|
node.setproperty(whatsit, prop)
|
||||||
|
if token.scan_keyword'xyz' then
|
||||||
|
prop.dest_type = 'xyz'
|
||||||
|
prop.xyz_zoom = token.scan_keyword'zoom' and token.scan_int()
|
||||||
|
maybe_gobble_cmd(spacer_cmd)
|
||||||
|
elseif token.scan_keyword'fitr' then
|
||||||
|
prop.dest_type = 'fitr'
|
||||||
|
maybe_gobble_cmd(spacer_cmd)
|
||||||
|
while true do
|
||||||
|
if token.scan_keyword'width' then
|
||||||
|
prop.width = token.scan_dimen()
|
||||||
|
elseif token.scan_keyword'height' then
|
||||||
|
prop.height = token.scan_dimen()
|
||||||
|
elseif token.scan_keyword'depth' then
|
||||||
|
prop.depth = token.scan_dimen()
|
||||||
|
else
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif token.scan_keyword'fitbh' then
|
||||||
|
prop.dest_type = 'fitbh'
|
||||||
|
maybe_gobble_cmd(spacer_cmd)
|
||||||
|
elseif token.scan_keyword'fitbv' then
|
||||||
|
prop.dest_type = 'fitbv'
|
||||||
|
maybe_gobble_cmd(spacer_cmd)
|
||||||
|
elseif token.scan_keyword'fitb' then
|
||||||
|
prop.dest_type = 'fitb'
|
||||||
|
maybe_gobble_cmd(spacer_cmd)
|
||||||
|
elseif token.scan_keyword'fith' then
|
||||||
|
prop.dest_type = 'fith'
|
||||||
|
maybe_gobble_cmd(spacer_cmd)
|
||||||
|
elseif token.scan_keyword'fitv' then
|
||||||
|
prop.dest_type = 'fitv'
|
||||||
|
maybe_gobble_cmd(spacer_cmd)
|
||||||
|
elseif token.scan_keyword'fit' then
|
||||||
|
prop.dest_type = 'fit'
|
||||||
|
maybe_gobble_cmd(spacer_cmd)
|
||||||
|
else
|
||||||
|
error[[Unsupported dest type]]
|
||||||
|
end
|
||||||
|
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.
|
||||||
|
@ -52,6 +52,9 @@ function token.luacmd(name, func, ...)
|
|||||||
end
|
end
|
||||||
local properties = node.direct.get_properties_table()
|
local properties = node.direct.get_properties_table()
|
||||||
node.direct.properties = properties
|
node.direct.properties = properties
|
||||||
|
function node.direct.get_properties_table()
|
||||||
|
return properties
|
||||||
|
end
|
||||||
-- setmetatable(node.direct.get_properties_table(), {
|
-- setmetatable(node.direct.get_properties_table(), {
|
||||||
-- __index = function(t, id)
|
-- __index = function(t, id)
|
||||||
-- local new = {}
|
-- local new = {}
|
||||||
|
@ -259,8 +259,8 @@ function nodehandler.hlist(p, list, x0, y, outerlist, origin, level)
|
|||||||
else
|
else
|
||||||
local dim = dirnodes[n]
|
local dim = dirnodes[n]
|
||||||
if dim then
|
if dim then
|
||||||
|
x = x + (2*direction-1) * dim
|
||||||
direction = 1-direction
|
direction = 1-direction
|
||||||
x = x + (2*newdir-1) * dim
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
Loading…
Reference in New Issue
Block a user