Update pdf_{save,restore,matrix}

This commit is contained in:
Marcel Krüger 2020-06-04 23:30:46 +02:00
parent adb3ab6bad
commit 9a3e7e7772
2 changed files with 68 additions and 49 deletions

View File

@ -114,6 +114,38 @@ end
local function sp2bp(sp)
return sp/65781.76
end
local function projected(m, x, y, w)
w = w or 1
return x*m[1] + y*m[3] + w*m[5], x*m[2] + y*m[4] + w*m[6]
end
local do_setmatrix do
local numberpattern = (lpeg.R'09'^0 * ('.' * lpeg.R'09'^0)^-1)/tonumber
local matrixpattern = numberpattern * ' ' * numberpattern * ' ' * numberpattern * ' ' * numberpattern
function whatsithandler.pdf_setmatrix(p, n, x, y, outer)
write_matrix(p, a, b, c, d, e, f)
end
local function do_setmatrix(prop, p, n, x, y, outer)
local m = p.matrix
local a, b, c, d = matrixpattern:match(prop.data)
local e, f = (1-a)*x-c*y, (1-d)*y-b*x -- Emulate that the origin is at x, y for this transformation
-- (We could also first translate by (-x, -y), then apply the matrix
-- and translate back, but this is more direct)
a, b = projected(m, a, b, 0)
c, d = projected(m, c, d, 0)
e, f = projected(m, e, f, 1)
m[1], m[2], m[3], m[4], m[5], m[6] = a, b, c, d, e, f
end
end
local function do_save(prop, p, n, x, y, outer)
pdf.write('page', 'q', x, y, p)
local lastmatrix = p.matrix
p.matrix = {[0] = lastmatrix, table.unpack(lastmatrix)}
end
local function do_restore(prop, p, n, x, y, outer)
-- TODO: Check x, y
pdf.write('page', 'Q', x, y, p)
p.matrix = p.matrix[0]
end
local function do_dest(prop, p, n, x, y)
-- TODO: Apply matrix
assert(cur_page, "Destinations can not appear outside of a page")
@ -246,6 +278,26 @@ token.luacmd("pdfextension", function(_, imm)
data = literal,
})
node.write(whatsit)
elseif token.scan_keyword"push" then
local whatsit = node.new(whatsit_id, whatsits.pdf_push)
node.setproperty(whatsit, {
handle = do_push,
})
node.write(whatsit)
elseif token.scan_keyword"setmatrix" then
local matrix = token.scan_string()
local whatsit = node.new(whatsit_id, whatsits.pdf_setmatrix)
node.setproperty(whatsit, {
handle = do_setmatrix,
data = matrix,
})
node.write(whatsit)
elseif token.scan_keyword"pop" then
local whatsit = node.new(whatsit_id, whatsits.pdf_pop)
node.setproperty(whatsit, {
handle = do_pop,
})
node.write(whatsit)
elseif token.scan_keyword"info" then
infodir = infodir .. token.scan_string()
elseif token.scan_keyword"catalog" then

View File

@ -74,21 +74,6 @@ local function projected_point(m, x, y, w)
w = w or 1
return x*m[1] + y*m[3] + w*m[5], x*m[2] + y*m[4] + w*m[6]
end
local function pdfsave(p, x, y)
local lastmatrix = p.matrix
p.matrix = {[0] = lastmatrix, table.unpack(lastmatrix)}
end
local function pdfmatrix(p, a, b, c, d, e, f)
local m = p.matrix
a, b = projected_point(m, a, b, 0)
c, d = projected_point(m, c, d, 0)
e, f = projected_point(m, e, f, 1)
m[1], m[2], m[3], m[4], m[5], m[6] = a, b, c, d, e, f
end
local function pdfrestore(p, x, y)
-- TODO: Check x, y
p.matrix = p.matrix[0]
end
local function sp2bp(sp)
return sp/65781.76
end
@ -151,21 +136,6 @@ local function toglyph(p, fid, x, y, exfactor)
p.mode = glyph
p.pending[1] = "[("
end
local function write_matrix(p, a, b, c, d, e, f)
local pending = p.pending_matrix
if p.mode ~= cm_pending then
topage(p)
p.mode = cm_pending
pending[1], pending[2], pending[3], pending[4], pending[5], pending[6] = a, b, c, d, e, f
return
else
a, b = projected_point(pending, a, b, 0)
c, d = projected_point(pending, c, d, 0)
e, f = projected_point(pending, e, f, 1)
pending[1], pending[2], pending[3], pending[4], pending[5], pending[6] = a, b, c, d, e, f
return
end
end
local linkcontext = {}
-- local function get_action_attr(p, action)
-- if action.action_type == 3 then
@ -508,23 +478,6 @@ function nodehandler.whatsit(p, n, ...) -- Whatsit?
return whatsithandler[getsubtype(n)](p, n, ...)
end
--[[ -- These use the old whatsit handling system which might get removed.
function whatsithandler.pdf_save(p, n, x, y, outer)
topage(p)
p.strings[#p.strings + 1] = 'q'
pdfsave(p, x, y)
end
function whatsithandler.pdf_restore(p, n, x, y, outer)
topage(p)
p.strings[#p.strings + 1] = 'Q'
pdfrestore(p, x, y)
end
local numberpattern = (lpeg.R'09'^0 * ('.' * lpeg.R'09'^0)^-1)/tonumber
local matrixpattern = numberpattern * ' ' * numberpattern * ' ' * numberpattern * ' ' * numberpattern
function whatsithandler.pdf_setmatrix(p, n, x, y, outer)
local a, b, c, d = matrixpattern:match(n.data)
local e, f = (1-a)*x-c*y, (1-d)*y-b*x
write_matrix(p, a, b, c, d, e, f)
end
function whatsithandler.pdf_start_link(p, n, x, y, outer, _, level)
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
@ -544,6 +497,20 @@ function pdf._latelua(p, x, y, func, ...)
global_p, global_x, global_y = p, x, y
return func(...)
end
function pdf.write_matrix(a, b, c, d, e, f, p)
e, f, p = e or 0, f or 0, p or global_p
local pending = p.pending_matrix
if p.mode ~= cm_pending then
topage(p)
p.mode = cm_pending
else
a, b = projected_point(pending, a, b, 0)
c, d = projected_point(pending, c, d, 0)
e, f = projected_point(pending, e, f, 1)
end
pending[1], pending[2], pending[3], pending[4], pending[5], pending[6] = a, b, c, d, e, f
end
local write_matrix = pdf.write_matrix
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 == "page" then
@ -558,10 +525,10 @@ function pdf.write(mode, text, x, y, p)
end
p.strings[#p.strings + 1] = text
elseif mode == "origin" then
write_matrix(p, 1, 0, 0, 1, x, y)
write_matrix(1, 0, 0, 1, x, y, p)
topage(p)
p.strings[#p.strings + 1] = text
write_matrix(p, 1, 0, 0, 1, -x, -y)
write_matrix(1, 0, 0, 1, -x, -y, p)
else
write(format('Literal type %s unsupported', mode))
end