diff options
author | Karl Berry <karl@freefriends.org> | 2020-03-05 00:48:46 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2020-03-05 00:48:46 +0000 |
commit | f210bce174e1f2f05305ab03e88e120a1cbfc4da (patch) | |
tree | 5c4e2ad096b5c745e859516ac3196fa0864292d5 /Master/texmf-dist/tex/context/base/mkiv/lpdf-pde.lua | |
parent | 35fd641a3546acc0c62e0aa7f134888e36da30d4 (diff) |
context (from cont-tmf.zip of Feb 17 16:00, size 116339406)
git-svn-id: svn://tug.org/texlive/trunk@54086 c570f23f-e606-0410-a88d-b1316a301751
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.lua | 317 |
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 |