Implement PDF compression

This commit is contained in:
Marcel Krüger 2020-06-13 14:34:53 +02:00
parent a0fb4684b3
commit e1325c6c40
4 changed files with 21 additions and 8 deletions

View File

@ -1,4 +1,5 @@
local pdf = pdf local pdf = pdf
local pdfvariable = pdf.variable
local writer = require'luametalatex-nodewriter' local writer = require'luametalatex-nodewriter'
local newpdf = require'luametalatex-pdf' local newpdf = require'luametalatex-pdf'
local nametree = require'luametalatex-pdf-nametree' local nametree = require'luametalatex-pdf-nametree'
@ -35,9 +36,9 @@ 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'
voff.kern = tex.voffset + pdf.variable.vorigin voff.kern = tex.voffset + pdfvariable.vorigin
voff.next = token.scan_list() voff.next = token.scan_list()
voff.next.shift = tex.hoffset + pdf.variable.horigin voff.next.shift = tex.hoffset + pdfvariable.horigin
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
@ -94,7 +95,7 @@ callback.register("stop_run", function()
pfile:indirect(id, require'luametalatex-pdf-font'(pfile, f, sorted)) pfile:indirect(id, require'luametalatex-pdf-font'(pfile, f, sorted))
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", pdfvariable.majorversion, pdfvariable.minorversion)
local destnames = {} local destnames = {}
for k,obj in next, dests do for k,obj in next, dests do
if pfile:written(obj) then if pfile:written(obj) then
@ -235,7 +236,7 @@ local function write_link(p, link)
end end
local function addlinkpoint(p, link, x, y, list, kind) local function addlinkpoint(p, link, x, y, list, kind)
local quads = link.quads local quads = link.quads
local off = pdf.variable.linkmargin local off = pdfvariable.linkmargin
x = kind == 'start' and x-off or x+off 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)

View File

@ -46,7 +46,7 @@
end end
local pdf_params = {} local pdf_params = {}
pdf.variable_tokens = pdf_params pdf.variable_tokens = pdf_params
pdf.variable = setmetatable({}, { setmetatable(pdf.variable, {
__index = function(t, k) __index = function(t, k)
local v = pdf_params[k] local v = pdf_params[k]
if v then if v then
@ -99,8 +99,8 @@
\pdfAlloc{dimen}{linkmargin}{0pt} \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}
\pdfAlloc{count}{objcompresslevel}{0} % see above \pdfAlloc{count}{objcompresslevel}{0} % 0 is actually the only supported value right now, so this is basically ignored
\pdfAlloc{toks}{pageresources}{{}} \pdfAlloc{toks}{pageresources}{{}}
\texAlloc{count}{bodydirection}{0} \texAlloc{count}{bodydirection}{0}

View File

@ -45,6 +45,7 @@ pdf = {
getfontname = function(id) -- No font sharing getfontname = function(id) -- No font sharing
return id return id
end, end,
variable = {},
} }
local olddefinefont = font.define local olddefinefont = font.define
function font.define(f) function font.define(f)

View File

@ -7,6 +7,8 @@ local pairs = pairs
local setmetatable = setmetatable local setmetatable = setmetatable
local assigned = {} local assigned = {}
local delayed = {} local delayed = {}
local compress = xzip.compress
local pdfvariable = pdf.variable
-- slightly tricky interface: No/nil return means that the objects content -- slightly tricky interface: No/nil return means that the objects content
-- isn't known yet, while false indicates a delayed object. -- isn't known yet, while false indicates a delayed object.
local function written(pdf, num) local function written(pdf, num)
@ -26,7 +28,16 @@ local function stream(pdf, num, dict, content, isfile, raw)
content = f:read'a' content = f:read'a'
f:close() f:close()
end end
pdf.file:write(format('%i 0 obj\n<<%s/Length %i>>stream\n', num, dict, #content)) local level = not raw and pdfvariable.compresslevel or 0
local filter = ''
if level > 0 then
local compressed = compress(content, level)
if #compressed < #content + 19 then -- Filter has some overhead
filter = "/Filter/FlateDecode"
content = compressed
end
end
pdf.file:write(format('%i 0 obj\n<<%s%s/Length %i>>stream\n', num, dict, filter, #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