107 lines
3.1 KiB
Lua
107 lines
3.1 KiB
Lua
|
local box_fallback = {
|
||
|
BleedBox = "CropBox",
|
||
|
TrimBox = "CropBox",
|
||
|
ArtBox = "CropBox",
|
||
|
CropBox = "MediaBox",
|
||
|
}
|
||
|
|
||
|
local boxmap = {
|
||
|
media = "MediaBox",
|
||
|
crop = "CropBox",
|
||
|
bleed = "BleedBox",
|
||
|
trim = "TrimBox",
|
||
|
art = "ArtBox",
|
||
|
}
|
||
|
|
||
|
-- FIXME:
|
||
|
local function to_sp(bp) return bp*65781.76//1 end
|
||
|
local function to_bp(sp) return sp/65781.76 end
|
||
|
|
||
|
local function get_box(page, box)
|
||
|
box = boxmap[box]
|
||
|
while box do
|
||
|
local found = pdfe.getbox(page, box)
|
||
|
if found then
|
||
|
return {to_sp(found[1]), to_sp(found[2]), to_sp(found[3]), to_sp(found[4])}
|
||
|
end
|
||
|
box = box_fallback[box]
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local pdf_functions = {}
|
||
|
|
||
|
local function open_pdfe(img)
|
||
|
local file = pdfe.open(img.filepath)
|
||
|
do
|
||
|
local userpassword = img.userpassword
|
||
|
local ownerpassword = img.ownerpassword
|
||
|
if userpassword or ownerpassword then
|
||
|
pdfe.unencrypt(file, userpassword, ownerpassword)
|
||
|
end
|
||
|
end
|
||
|
local status = pdfe.getstatus(file)
|
||
|
if status >= 0 then
|
||
|
return file
|
||
|
elseif status == -1 then
|
||
|
error[[PDF image is encrypted. Please provide the decryption key.]]
|
||
|
elseif status == -2 then
|
||
|
error[[PDF image could not be opened.]]
|
||
|
else
|
||
|
assert(false)
|
||
|
end
|
||
|
end
|
||
|
function pdf_functions.scan(img)
|
||
|
local file = open_pdfe(img)
|
||
|
img.pages = pdfe.getnofpages(file)
|
||
|
img.page = img.page or 1
|
||
|
if img.page > img.pages then
|
||
|
error[[Not enough pages in PDF image]]
|
||
|
end
|
||
|
local page = pdfe.getpage(file, img.page)
|
||
|
local bbox = img.bbox or get_box(page, img.pagebox or 'crop') or {0, 0, 0, 0}
|
||
|
img.bbox = bbox
|
||
|
img.rotation = (360 - (page.Rotate or 0)) % 360
|
||
|
assert(img.rotation % 90 == 0, "Invalid /Rotate")
|
||
|
img.rotation = img.rotation / 90
|
||
|
if img.rotation < 0 then img.rotation = img.rotation + 4 end
|
||
|
img.xsize = bbox[3] - bbox[1]
|
||
|
img.ysize = bbox[4] - bbox[2]
|
||
|
img.xres, img.yres = nil, nil
|
||
|
end
|
||
|
|
||
|
local pdfe_deepcopy = require'luametalatex-pdfe-deepcopy'
|
||
|
function pdf_functions.write(pfile, img)
|
||
|
local file = open_pdfe(img)
|
||
|
local page = pdfe.getpage(file, img.page)
|
||
|
local bbox = img.bbox
|
||
|
local dict = string.format("/Subtype/Form/BBox[%f %f %f %f]/Resources %s", bbox[1], bbox[2], bbox[3], bbox[4], pdfe_deepcopy(file, img.filepath, pfile, pdfe.getfromdictionary(page, 'Resources')))
|
||
|
local content, raw = page.Contents
|
||
|
-- Three cases: Contents is a stream, so copy the stream (Remember to copy filter if necessary)
|
||
|
-- Contents is an array of streams, so append all the streams as a new stream
|
||
|
-- Contents is missing. Then create an empty stream.
|
||
|
local type = pdfe.type(content)
|
||
|
if type == 'pdfe.stream' then
|
||
|
raw = true
|
||
|
for i=1,#content do
|
||
|
local key, type, value, detail = pdfe.getfromstream(content, i)
|
||
|
dict = dict .. pdfe_deepcopy(file, img.filepath, pfile, 5, key) .. ' ' .. pdfe_deepcopy(file, img.filepath, pfile, type, value, detail)
|
||
|
end
|
||
|
content = content(false)
|
||
|
elseif type == 'pdfe.array' then
|
||
|
local array = content
|
||
|
content = ''
|
||
|
for i=1,#array do
|
||
|
content = content .. array[i](true)
|
||
|
end
|
||
|
else
|
||
|
content = ''
|
||
|
end
|
||
|
local attr = img.attr
|
||
|
if attr then
|
||
|
dict = dict .. attr
|
||
|
end
|
||
|
pfile:stream(img.objnum, dict, content, nil, raw)
|
||
|
end
|
||
|
|
||
|
return pdf_functions
|