summaryrefslogtreecommitdiff
path: root/tex/context/base/mkxl/lpdf-xmp.lmt
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/mkxl/lpdf-xmp.lmt')
-rw-r--r--tex/context/base/mkxl/lpdf-xmp.lmt260
1 files changed, 186 insertions, 74 deletions
diff --git a/tex/context/base/mkxl/lpdf-xmp.lmt b/tex/context/base/mkxl/lpdf-xmp.lmt
index a5be8bfe0..ce5d69a48 100644
--- a/tex/context/base/mkxl/lpdf-xmp.lmt
+++ b/tex/context/base/mkxl/lpdf-xmp.lmt
@@ -8,10 +8,13 @@ if not modules then modules = { } end modules ['lpdf-xmp'] = {
}
local tostring, type = tostring, type
-local format, gsub = string.format, string.gsub
+local format, gsub, match = string.format, string.gsub, string.match
+local concat = table.concat
+local settings_to_array = utilities.parsers.settings_to_array
local utfchar = utf.char
local xmlfillin = xml.fillin
local md5HEX = md5.HEX
+local osdate, ostime, ostimezone, osuuid = os.date, os.time, os.timezone, os.uuid
local trace_xmp = false trackers.register("backend.xmp", function(v) trace_xmp = v end)
local trace_info = false trackers.register("backend.info", function(v) trace_info = v end)
@@ -26,8 +29,9 @@ local codeinjections = pdfbackend.codeinjections
local lpdf = lpdf
local pdfdictionary = lpdf.dictionary
local pdfconstant = lpdf.constant
+local pdfunicode = lpdf.unicode
+local pdfstring = lpdf.string
local pdfreference = lpdf.reference
-local pdfgetmetadata = lpdf.getmetadata
local pdfflushstreamobject = lpdf.flushstreamobject
-- The XMP packet wrapper is kind of fixed, see page 10 of XMPSpecificationsPart1.pdf from
@@ -40,7 +44,8 @@ local xpacket = format ( [[
<?xpacket end="w"?>]], utfchar(0xFEFF) )
-local mapping = {
+local unknown = { false, false }
+local mapping = table.setmetatableindex ( {
-- user defined keys (pdfx:)
["ConTeXt.Jobname"] = { "context", "rdf:Description/pdfx:ConTeXt.Jobname" },
["ConTeXt.Time"] = { "date", "rdf:Description/pdfx:ConTeXt.Time" },
@@ -89,72 +94,113 @@ local mapping = {
["AuthorsPosition"] = { "metadata", "rdf:Description/photoshop:AuthorsPosition" },
["Copyright"] = { "metadata", "rdf:Description/photoshop:Copyright" },
["CaptionWriter"] = { "metadata", "rdf:Description/photoshop:CaptionWriter" },
-}
+}, function() return unknown end )
-local included = backends.included
-local lpdfid = lpdf.id
-function lpdf.id() -- overload of ini
- return lpdfid(included.date)
-end
+local metadata = nil
+local trailerid = true
+local creationdate = false
+local modificationdate = false
-local trailerid = nil
-local dates = nil
+local function pdftimestamp(str)
+ local t = type(str)
+ if t == "string" then
+ local Y, M, D, h, m, s, Zs, Zh, Zm = match(str,"^(%d%d%d%d)%-(%d%d)%-(%d%d)T(%d%d):(%d%d):(%d%d)([%+%-])(%d%d):(%d%d)$")
+ return Y and format("D:%s%s%s%s%s%s%s%s'%s'",Y,M,D,h,m,s,Zs,Zh,Zm)
+ else
+ return osdate("D:%Y%m%d%H%M%S",t == "number" and str or ostime()) -- maybe "!D..." : universal time
+ end
+end
-local function update()
- if trailer_id then
- local b = toboolean(trailer_id) or trailer_id == ""
- if b then
- trailer_id = "This file is processed by ConTeXt and LuaTeX."
- else
- trailer_id = tostring(trailer_id)
- end
- local h = md5HEX(trailer_id)
- if b then
- report_info("using frozen trailer id")
- else
- report_info("using hashed trailer id %a (%a)",trailer_id,h)
- end
- trailerid = format("[<%s> <%s>]",h,h)
+local function pdfgetmetadata()
+ if not metadata then
+ local contextversion = environment.version
+ local luatexversion = format("%1.2f",LUATEXVERSION)
+ local luatexfunctionality = tostring(LUATEXFUNCTIONALITY)
+ local jobname = environment.jobname or tex.jobname or "unknown"
+ local documentid = trailerid and ("uuid:" .. osuuid()) or "no unique document id here"
+ local instanceid = trailerid and ("uuid:" .. osuuid()) or "no unique instance id here"
+ metadata = creationdate and {
+ producer = format("LuaMetaTeX-%s",luatexversion),
+ creator = format("LuaMetaTeX %s %s + ConTeXt LMTX %s",luatexversion,luatexfunctionality,contextversion),
+ luatexversion = luatexversion,
+ contextversion = contextversion,
+ luatexfunctionality = luatexfunctionality,
+ luaversion = tostring(LUAVERSION),
+ platform = os.platform,
+ creationdate = creationdate,
+ modificationdate = modificationdate,
+ id = format("%s | %s",jobname,creationdate),
+ documentid = documentid,
+ instanceid = instanceid,
+ jobname = jobname,
+ } or {
+ producer = "LuaMetaTeX",
+ creator = "LuaMetaTeX + ConTeXt LMTX",
+ id = jobname,
+ documentid = documentid,
+ instanceid = instanceid,
+ jobname = jobname,
+ }
+ -- inspect(metadata)
end
- --
- local t = type(dates)
- if t == "number" or t == "string" then
- local d = converters.totime(dates)
- if d then
- included.date = true
- included.id = "fake"
- report_info("forced date/time information %a will be used",lpdf.settime(d))
- trailerid = false
- elseif t == "string" then
- dates = toboolean(dates)
- included.date = dates
- if dates ~= false then
- included.id = true
- else
- report_info("no date/time but fake id information will be added")
- trailerid = true
- included.id = "fake"
+ return metadata
+end
+
+local function pdfsetmetadate(n,both)
+ if n then
+ n = converters.totime(n)
+ if n then
+ creationdate = osdate("%Y-%m-%dT%X",ostime(n)) .. ostimezone(true)
+ if both then
+ modificationdate = creationdate
end
end
end
+ return creationdate
end
-lpdf.registerdocumentfinalizer(update,"trailer id and dates",1)
+lpdf.pdftimestamp = pdftimestamp
-directives.register("backend.trailerid", function(v) trailerid = v end)
-directives.register("backend.date", function(v) dates = v end)
+function lpdf.gettrailerid()
+ if trailerid == true then
+ return md5.HEX(osuuid())
+ elseif type(trailerid) == "string" then
+ return md5.HEX(trailerid)
+ else
+ return false
+ end
+end
+
+-- string: use that, true: uuid, false: nothing
+
+directives.register("backend.trailerid", function(v)
+ trailerid = type(v) and v or toboolean(v)
+end)
-local function permitdetail(what)
- local m = mapping[what]
- if m then
- return included[m[1]] and m[2]
+-- year-mm-dd : use that for creation and modification
+
+local function setdates(v)
+ local t = type(v)
+ if t == "number" or t == "string" then
+ local d = converters.totime(v)
+ if d then
+ report_info("forced date/time information %a will be used",pdfsetmetadate(d,true))
+ return
+ end
+ end
+ if toboolean(v) then
+ creationdate = osdate("%Y-%m-%dT%X") .. ostimezone(true)
+ modificationdate = creationdate
else
- return included[what] and true or false
+ creationdate = false
+ modificationdate = false
end
end
-lpdf.permitdetail = permitdetail
+setdates(true)
+
+directives.register("backend.date", setdates)
-- maybe some day we will load the xmp file at runtime
@@ -195,7 +241,7 @@ local function valid_xmp()
end
function lpdf.addxmpinfo(tag,value,check)
- local pattern = permitdetail(tag)
+ local pattern = mapping[tag][2]
if type(pattern) == "string" then
xmlfillin(xmp or valid_xmp(),pattern,value,check)
end
@@ -207,7 +253,7 @@ local pdfaddtoinfo = lpdf.addtoinfo
local pdfaddxmpinfo = lpdf.addxmpinfo
function lpdf.addtoinfo(tag,pdfvalue,strvalue)
- local pattern = permitdetail(tag)
+ local pattern = mapping[tag][2]
if pattern then
pdfaddtoinfo(tag,pdfvalue)
end
@@ -234,24 +280,91 @@ end
-- flushing
-local add_xmp_blob = true directives.register("backend.xmp",function(v) add_xmp_blob = v end)
+local add_xmp_blob = true
+local indentity_done = false -- using "setupidentity = function() end" fails as the meaning is frozen in register
+
+local function setupidentity()
+ if not done then
+ --
+ local identity = interactions.general.getidentity()
+ local title = identity.title
+ local subtitle = identity.subtitle
+ local author = identity.author
+ local date = identity.date
+ local keywords = identity.keywords
+ --
+ if date and date ~= "" then
+ pdfsetmetadate(date)
+ end
+ if keywords then
+ keywords = concat(settings_to_array(keywords), " ")
+ end
+ --
+ local metadata = pdfgetmetadata()
+ local creator = metadata.creator
+ local contextversion = metadata.contextversion
+ local id = metadata.id
+ local jobname = metadata.jobname
+ local creator = metadata.creator
+ local creation = metadata.creationdate
+ local modification = metadata.modificationdate
+ --
+ if creator then
+ pdfaddtoinfo("Creator",pdfunicode(creator),creator)
+ end
+ if creation then
+ pdfaddtoinfo("CreationDate",pdfstring(pdftimestamp(creation)),creation)
+ end
+ if modification then
+ pdfaddtoinfo("ModDate",pdfstring(pdftimestamp(modification)),modification)
+ end
+ if id then
+ pdfaddtoinfo("ID",pdfstring(id),id) -- needed for pdf/x
+ end
+ --
+ if title ~= "" then
+ pdfaddtoinfo("Title",pdfunicode(title),title)
+ end
+ if subtitle ~= "" then
+ pdfaddtoinfo("Subject",pdfunicode(subtitle),subtitle)
+ end
+ if author ~= "" then
+ pdfaddtoinfo("Author",pdfunicode(author),author) -- '/Author' in /Info, 'Creator' in XMP
+ end
+ if keywords and keywords ~= "" then
+ pdfaddtoinfo("Keywords",pdfunicode(keywords),keywords)
+ end
+ --
+ if contextversion then
+ pdfaddtoinfo("ConTeXt.Version",contextversion)
+ end
+ if creation then
+ pdfaddtoinfo("ConTeXt.Time",creation)
+ end
+ if jobname then
+ pdfaddtoinfo("ConTeXt.Jobname",jobname)
+ end
+ --
+ pdfaddtoinfo("ConTeXt.Url","www.pragma-ade.com")
+ pdfaddtoinfo("ConTeXt.Support","contextgarden.net")
+ pdfaddtoinfo("TeX.Support","tug.org")
+ --
+ done = true
+ else
+ -- no need for a message
+ end
+end
local function flushxmpinfo()
commands.pushrandomseed()
- commands.setrandomseed(os.time())
-
- local documentid = "no unique document id here"
- local instanceid = "no unique instance id here"
+ commands.setrandomseed(ostime())
- local metadata = pdfgetmetadata()
- local time = metadata.time
- local producer = metadata.producer
- local creator = metadata.creator
-
- if included.id ~= "fake" then
- documentid = "uuid:" .. os.uuid()
- instanceid = "uuid:" .. os.uuid()
- end
+ local metadata = pdfgetmetadata()
+ local time = metadata.time
+ local producer = metadata.producer
+ local creator = metadata.creator
+ local documentid = metadata.documentid
+ local instanceid = metadata.instanceid
pdfaddtoinfo("Producer",producer)
pdfaddtoinfo("Creator",creator)
@@ -293,15 +406,14 @@ local function flushxmpinfo()
end
local r = pdfflushstreamobject(blob,md,false) -- uncompressed
lpdf.addtocatalog("Metadata",pdfreference(r))
+
end
commands.poprandomseed() -- hack
end
--- this will be enabled when we can inhibit compression for a stream at the lua end
-
+lpdf.registerpagefinalizer(setupidentity,"identity")
lpdf.registerdocumentfinalizer(flushxmpinfo,1,"metadata")
-directives.register("backend.verbosexmp", function(v)
- verbose = v
-end)
+directives.register("backend.xmp", function(v) add_xmp_blob = v end)
+directives.register("backend.verbosexmp", function(v) verbose = v end)