summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/context/base/mkiv/lpdf-pde.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/context/base/mkiv/lpdf-pde.lua')
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lpdf-pde.lua317
1 files changed, 175 insertions, 142 deletions
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-pde.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-pde.lua
index c1680137da2..ec1064a0dfd 100644
--- a/Master/texmf-dist/tex/context/base/mkiv/lpdf-pde.lua
+++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-pde.lua
@@ -41,7 +41,7 @@ if not modules then modules = { } end modules ['lpdf-epd'] = {
-- PPCRYPT_PASS -1 encryption present, need non-empty password
-- PPCRYPT_FAIL -2 invalid or unsupported encryption (eg. undocumented in pdf spec)
-local setmetatable, rawset, rawget, type, next = setmetatable, rawset, rawget, type, next
+local setmetatable, type, next = setmetatable, type, next
local tostring, tonumber, unpack = tostring, tonumber, unpack
local char, byte, find = string.char, string.byte, string.find
local abs = math.abs
@@ -60,29 +60,29 @@ if not (number and number.dimenfactors) then
require("util-dim")
end
-local epdf = pdfe
+local pdfe = pdfe
lpdf = lpdf or { }
local lpdf = lpdf
local lpdf_epdf = { }
-lpdf.epdf = lpdf_epdf
-
-local openPDF = epdf.open
-local newPDF = epdf.new
-local closePDF = epdf.close
-
-local getcatalog = epdf.getcatalog
-local getinfo = epdf.getinfo
-local gettrailer = epdf.gettrailer
-local getnofpages = epdf.getnofpages
-local getversion = epdf.getversion
-local getbox = epdf.getbox
-local getstatus = epdf.getstatus
-local unencrypt = epdf.unencrypt
-
-local dictionarytotable = epdf.dictionarytotable
-local arraytotable = epdf.arraytotable
-local pagestotable = epdf.pagestotable
-local readwholestream = epdf.readwholestream
+ lpdf.epdf = lpdf_epdf
+
+local pdfopen = pdfe.open
+local pdfnew = pdfe.new
+local pdfclose = pdfe.close
+
+local getcatalog = pdfe.getcatalog
+local getinfo = pdfe.getinfo
+local gettrailer = pdfe.gettrailer
+local getnofpages = pdfe.getnofpages
+local getversion = pdfe.getversion
+local getbox = pdfe.getbox
+local getstatus = pdfe.getstatus
+local unencrypt = pdfe.unencrypt
+
+local dictionarytotable = pdfe.dictionarytotable
+local arraytotable = pdfe.arraytotable
+local pagestotable = pdfe.pagestotable
+local readwholestream = pdfe.readwholestream
local getfromreference = pdfe.getfromreference
@@ -405,21 +405,25 @@ function resolvers.pages(document)
--
for pagenumber=1,nofpages do
local rawpagedata = rawpages[pagenumber]
- local pagereference = rawpagedata[3]
- local pageobject = rawpagedata[1]
- local pagedata = some_dictionary(pageobject,document)
- if pagedata and pageobject then
- pagedata.number = pagenumber
- pagedata.MediaBox = getbox(pageobject,"MediaBox")
- pagedata.CropBox = getbox(pageobject,"CropBox")
- pagedata.BleedBox = getbox(pageobject,"BleedBox")
- pagedata.ArtBox = getbox(pageobject,"ArtBox")
- pagedata.TrimBox = getbox(pageobject,"TrimBox")
- pages[pagenumber] = pagedata
- __xrefs__[pagedata] = pagereference
- __cache__[pagereference] = pagedata
+ if rawpagedata then
+ local pagereference = rawpagedata[3]
+ local pageobject = rawpagedata[1]
+ local pagedata = some_dictionary(pageobject,document)
+ if pagedata and pageobject then
+ pagedata.number = pagenumber
+ pagedata.MediaBox = getbox(pageobject,"MediaBox")
+ pagedata.CropBox = getbox(pageobject,"CropBox")
+ pagedata.BleedBox = getbox(pageobject,"BleedBox")
+ pagedata.ArtBox = getbox(pageobject,"ArtBox")
+ pagedata.TrimBox = getbox(pageobject,"TrimBox")
+ pages[pagenumber] = pagedata
+ __xrefs__[pagedata] = pagereference
+ __cache__[pagereference] = pagedata
+ else
+ report_epdf("missing pagedata for page %i, case %i",pagenumber,1)
+ end
else
- report_epdf("missing pagedata for page %i",i)
+ report_epdf("missing pagedata for page %i, case %i",pagenumber,2)
end
end
--
@@ -437,9 +441,9 @@ function lpdf_epdf.load(filename,userpassword,ownerpassword,fromstring)
statistics.starttiming(lpdf_epdf)
local __data__
if fromstring then
- __data__ = newPDF(filename,#filename)
+ __data__ = pdfnew(filename,#filename)
else
- __data__ = openPDF(filename)
+ __data__ = pdfopen(filename)
end
if __data__ then
if userpassword and getstatus(__data__) < 0 then
@@ -455,6 +459,8 @@ function lpdf_epdf.load(filename,userpassword,ownerpassword,fromstring)
if __data__ then
document = {
filename = filename,
+ nofcopied = 0,
+ copied = { },
__cache__ = { },
__xrefs__ = { },
__fonts__ = { },
@@ -481,6 +487,9 @@ function lpdf_epdf.load(filename,userpassword,ownerpassword,fromstring)
statistics.stoptiming(lpdf_epdf)
-- print(statistics.elapsedtime(lpdf_epdf))
end
+ if document then
+ nofloaded = nofloaded + 1
+ end
return document or nil
end
@@ -491,10 +500,9 @@ function lpdf_epdf.unload(filename)
if type(filename) == "string" then
local document = loaded[filename]
if document then
--- report_epdf("%04i closed: %s",nofloaded,filename)
--- nofloaded = nofloaded - 1
loaded[document] = nil
loaded[filename] = nil
+ pdfclose(document.__data__)
end
end
end
@@ -519,6 +527,7 @@ lpdf_epdf.expanded = expanded
local spaces = lpegpatterns.whitespace^1
local optspaces = lpegpatterns.whitespace^0
+local comment = P("%") * (1 - lpegpatterns.newline)^0
local numchar = P("\\")/"" * (R("09")^3/function(s) return char(tonumber(s,8)) end)
+ P("\\") * P(1)
local key = P("/") * C(R("AZ","az","09","__")^1)
@@ -527,7 +536,7 @@ local keyword = Ct(Cc("name") * key)
local operator = C((R("AZ","az")+P("*")+P("'")+P('"'))^1)
local grammar = P { "start",
- start = (keyword + number + V("dictionary") + V("array") + V("hexstring") + V("decstring") + spaces)^1,
+ start = (comment + keyword + number + V("dictionary") + V("array") + V("hexstring") + V("decstring") + spaces)^1,
keyvalue = key * optspaces * V("start"),
array = Ct(Cc("array") * P("[") * Ct(V("start")^1) * P("]")),
dictionary = Ct(Cc("dict") * P("<<") * Ct(V("keyvalue")^1) * P(">>")),
@@ -635,6 +644,8 @@ local function analyzefonts(document,resources) -- unfinished, see mtx-pdf for b
return fonts
end
+lpdf_epdf.analyzefonts = analyzefonts
+
local more = 0
local unic = nil -- cheaper than passing each time as Carg(1)
@@ -680,27 +691,34 @@ function lpdf_epdf.getpagecontent(document,pagenumber)
local size = #entry
local operator = entry[size]
if operator == "Tf" then
- font = fonts[entry[1]]
- unic = font.tounicode
- elseif operator == "TJ" then -- { array, TJ }
- local list = entry[1]
+ font = fonts[entry[1][2]]
+ unic = font and font.tounicode or { }
+ elseif operator == "TJ" then
+ local data = entry[1] -- { "array", { ... } }
+ local list = data[2] -- { { ... }, { ... } }
for i=1,#list do
local li = list[i]
- if type(li) == "table" then
- if li[1] == "hex" then
+-- if type(li) == "table" then
+ local kind = li[1]
+ if kind == "hex" then
list[i] = lpegmatch(p_hex_to_utf,li[2])
- else
+ elseif kind == "string" then
list[i] = lpegmatch(p_dec_to_utf,li[2])
+ else
+ list[i] = li[2] -- kern
end
- else
- -- kern
- end
+-- else
+-- -- kern
+-- end
end
- elseif operator == "Tj" or operator == "'" or operator == '"' then -- { string, Tj } { string, ' } { n, m, string, " }
- local list = entry[size-1]
- if list[1] == "hex" then
+ elseif operator == "Tj" or operator == "'" or operator == '"' then
+ -- { string, Tj } { string, ' } { n, m, string, " }
+ local data = entry[size-1]
+ local list = data[2]
+ local kind = list[1]
+ if kind == "hex" then
list[2] = lpegmatch(p_hex_to_utf,li[2])
- else
+ elseif kind == "string" then
list[2] = lpegmatch(p_dec_to_utf,li[2])
end
end
@@ -729,25 +747,32 @@ function lpdf_epdf.contenttotext(document,list) -- maybe signal fonts
local size = #entry
local operator = entry[size]
if operator == "Tf" then
- last_f = entry[2]
+ last_f = entry[2][2] -- size
elseif operator == "TJ" then
- local list = entry[1]
+ local data = entry[1] -- { "array", { ... } }
+ local list = data[2] -- { { ... }, { ... } }
for i=1,#list do
local li = list[i]
- if type(li) == "string" then
+ local kind = type(li)
+ if kind == "string" then
last = last + 1
text[last] = li
- elseif li < -50 then
+ elseif kind == "number" and li < -50 then
last = last + 1
text[last] = " "
end
end
- line = concat(list)
elseif operator == "Tj" then
last = last + 1
- text[last] = entry[size-1]
+ local li = entry[size-1]
+ local kind = type(li)
+ if kind == "string" then
+ last = last + 1
+ text[last] = li
+ end
elseif operator == "cm" or operator == "Tm" then
- local ty = entry[6]
+ local data = entry
+ local ty = entry[6][2]
local dy = abs(last_y - ty)
if dy > linefactor*last_f then
if last > 0 then
@@ -793,7 +818,7 @@ function lpdf_epdf.getstructure(document,list) -- just a test
end
end
-if img then do
+if images then do
-- This can be made a bit faster (just get raw data and pass it) but I will
-- do that later. In the end the benefit is probably neglectable.
@@ -887,6 +912,8 @@ if img then do
value = pdfnull()
elseif kind == reference_object_code then
value = deepcopyobject(xref,copied,entry)
+ elseif entry == nil then
+ value = pdfnull()
else
value = tostring(entry)
end
@@ -999,6 +1026,8 @@ if img then do
local openpdf = lpdf_epdf.load
local closepdf = lpdf_epdf.unload
+ -- todo: keep track of already open files
+
local function newpdf(str,userpassword,ownerpassword)
return openpdf(str,userpassword,ownerpassword,true)
end
@@ -1019,7 +1048,7 @@ if img then do
local root = pdfdoc.Catalog
local page = pdfdoc.pages[pagenumber]
if page then
- local sizetag = sizes[size or "crop"] or sizes.cro
+ local sizetag = sizes[size or "crop"] or sizes.crop
local mediabox = page.MediaBox or { 0, 0, 0, 0 }
local cropbox = page[sizetag] or mediabox
return {
@@ -1046,92 +1075,96 @@ if img then do
local page = pdfdoc.pages[pagenumber or 1]
local pageinfo = querypdf(pdfdoc,pagenumber)
local contents = page.Contents
- local xref = pdfdoc.__xrefs__
- local copied = pdfdoc.__copied__
- if compact and lpdf_epdf.plugin then
- plugins = lpdf_epdf.plugin(pdfdoc,xref,copied,page)
- end
- local xobject = pdfdictionary {
- Type = pdfconstant("XObject"),
- Subtype = pdfconstant("Form"),
- FormType = 1,
- Group = copyobject(xref,copied,page,"Group"),
- LastModified = copyobject(xref,copied,page,"LastModified"),
- Metadata = copyobject(xref,copied,page,"Metadata"),
- PieceInfo = copyobject(xref,copied,page,"PieceInfo"),
- Resources = copyresources(pdfdoc,xref,copied,page),
- SeparationInfo = copyobject(xref,copied,page,"SeparationInfo"),
- } + attr
- if attributes then
- for k, v in expanded(attributes) do
- page[k] = v -- maybe nested
+ if contents then
+ local xref = pdfdoc.__xrefs__
+ local copied = pdfdoc.__copied__
+ if compact and lpdf_epdf.plugin then
+ plugins = lpdf_epdf.plugin(pdfdoc,xref,copied,page)
end
- end
- local content = ""
- local nolength = nil
- local ctype = contents.__type__
- -- we always recompress because image object streams can not be
- -- influenced (yet)
- if ctype == stream_object_code then
- if stripmarked then
- content = contents() -- uncompressed
- local stripped = lpdf_epdf.stripcontent(content)
- if stripped ~= content then
- -- report("%i bytes stripped on page %i",#content-#stripped,pagenumber or 1)
- content = stripped
+ local xobject = pdfdictionary {
+ Type = pdfconstant("XObject"),
+ Subtype = pdfconstant("Form"),
+ FormType = 1,
+ Group = copyobject(xref,copied,page,"Group"),
+ LastModified = copyobject(xref,copied,page,"LastModified"),
+ Metadata = copyobject(xref,copied,page,"Metadata"),
+ PieceInfo = copyobject(xref,copied,page,"PieceInfo"),
+ Resources = copyresources(pdfdoc,xref,copied,page),
+ SeparationInfo = copyobject(xref,copied,page,"SeparationInfo"),
+ } + attr
+ if attributes then
+ for k, v in expanded(attributes) do
+ page[k] = v -- maybe nested
end
- elseif recompress then
- content = contents() -- uncompressed
- else
- local Filter = copyobject(xref,copied,contents,"Filter")
- local Length = copyobject(xref,copied,contents,"Length")
- if Length and Filter then
- nolength = true
- xobject.Length = Length
- xobject.Filter = Filter
- content = contents(false) -- uncompressed
- else
+ end
+ local content = ""
+ local nolength = nil
+ local ctype = contents.__type__
+ -- we always recompress because image object streams can not be
+ -- influenced (yet)
+ if ctype == stream_object_code then
+ if stripmarked then
+ content = contents() -- uncompressed
+ local stripped = lpdf_epdf.stripcontent(content)
+ if stripped ~= content then
+ -- report("%i bytes stripped on page %i",#content-#stripped,pagenumber or 1)
+ content = stripped
+ end
+ elseif recompress then
content = contents() -- uncompressed
+ else
+ local Filter = copyobject(xref,copied,contents,"Filter")
+ local Length = copyobject(xref,copied,contents,"Length")
+ if Length and Filter then
+ nolength = true
+ xobject.Length = Length
+ xobject.Filter = Filter
+ content = contents(false) -- uncompressed
+ else
+ content = contents() -- uncompressed
+ end
+ end
+ elseif ctype == array_object_code then
+ content = { }
+ for i=1,#contents do
+ content[i] = contents[i]() -- uncompressed
end
+ content = concat(content," ")
end
- elseif ctype == array_object_code then
- content = { }
- for i=1,#contents do
- content[i] = contents[i]() -- uncompressed
+ -- still not nice: we double wrap now
+ plugins = nil
+ local rotation = pageinfo.rotation
+ local boundingbox = pageinfo.boundingbox
+ local transform = nil
+ if rotation == 90 then
+ transform = 3
+ elseif rotation == 180 then
+ transform = 2
+ elseif rotation == 270 then
+ transform = 1
+ elseif rotation > 1 and rotation < 4 then
+ transform = rotation
end
- content = concat(content," ")
- end
- -- still not nice: we double wrap now
- plugins = nil
- local rotation = pageinfo.rotation
- local boundingbox = pageinfo.boundingbox
- local transform = nil
- if rotation == 90 then
- transform = 3
- elseif rotation == 180 then
- transform = 2
- elseif rotation == 270 then
- transform = 1
- elseif rotation > 1 and rotation < 4 then
- transform = rotation
+ xobject.BBox = pdfarray {
+ boundingbox[1] * bpfactor,
+ boundingbox[2] * bpfactor,
+ boundingbox[3] * bpfactor,
+ boundingbox[4] * bpfactor,
+ }
+ -- maybe like bitmaps
+ return createimage { -- beware: can be a img.new or a dummy
+ bbox = boundingbox,
+ transform = transform,
+ nolength = nolength,
+ nobbox = true,
+ notype = true,
+ stream = content, -- todo: no compress, pass directly also length, filter etc
+ attr = xobject(),
+ kind = images.types.stream,
+ }
+ else
+ -- maybe report an error
end
- xobject.BBox = pdfarray {
- boundingbox[1] * bpfactor,
- boundingbox[2] * bpfactor,
- boundingbox[3] * bpfactor,
- boundingbox[4] * bpfactor,
- }
- -- maybe like bitmaps
- return createimage { -- beware: can be a img.new or a dummy
- bbox = boundingbox,
- transform = transform,
- nolength = nolength,
- nobbox = true,
- notype = true,
- stream = content, -- todo: no compress, pass directly also length, filter etc
- attr = xobject(),
- kind = images.types.stream,
- }
end
end