summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv/lpdf-epa.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/mkiv/lpdf-epa.lua')
-rw-r--r--tex/context/base/mkiv/lpdf-epa.lua751
1 files changed, 637 insertions, 114 deletions
diff --git a/tex/context/base/mkiv/lpdf-epa.lua b/tex/context/base/mkiv/lpdf-epa.lua
index 89b2c6e0e..ee3b6d43d 100644
--- a/tex/context/base/mkiv/lpdf-epa.lua
+++ b/tex/context/base/mkiv/lpdf-epa.lua
@@ -6,47 +6,72 @@ if not modules then modules = { } end modules ['lpdf-epa'] = {
license = "see context related readme files"
}
--- This is a rather experimental feature and the code will probably change.
+-- Links can also have quadpoint
-local type, tonumber = type, tonumber
-local format, gsub, lower = string.format, string.gsub, string.lower
+local type, tonumber, next = type, tonumber, next
+local format, gsub, lower, find = string.format, string.gsub, string.lower, string.find
local formatters = string.formatters
+local concat, merged = table.concat, table.merged
local abs = math.abs
local expandname = file.expandname
local allocate = utilities.storage.allocate
+local bor, band = bit32.bor, bit32.band
local isfile = lfs.isfile
------ lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
+local trace_links = false trackers.register("figures.links", function(v) trace_links = v end)
+local trace_comments = false trackers.register("figures.comments", function(v) trace_comments = v end)
+local trace_fields = false trackers.register("figures.fields", function(v) trace_fields = v end)
+local trace_outlines = false trackers.register("figures.outlines", function(v) trace_outlines = v end)
-local trace_links = false trackers.register("figures.links", function(v) trace_links = v end)
-local trace_outlines = false trackers.register("figures.outliness", function(v) trace_outlines = v end)
+local report_link = logs.reporter("backend","link")
+local report_comment = logs.reporter("backend","comment")
+local report_field = logs.reporter("backend","field")
+local report_outline = logs.reporter("backend","outline")
-local report_link = logs.reporter("backend","link")
-local report_comment = logs.reporter("backend","comment")
-local report_field = logs.reporter("backend","field")
-local report_outline = logs.reporter("backend","outline")
+local nodeinjections = backends.pdf.nodeinjections
-local epdf = epdf
-local backends = backends
-local lpdf = lpdf
-local context = context
+local pdfarray = lpdf.array
+local pdfdictionary = lpdf.dictionary
+local pdfconstant = lpdf.constant
+local pdfreserveobject = lpdf.reserveobject
+local pdfreference = lpdf.reference
-local loadpdffile = lpdf.epdf.load
+local pdfcopyboolean = lpdf.copyboolean
+local pdfcopyunicode = lpdf.copyunicode
+local pdfcopyarray = lpdf.copyarray
+local pdfcopydictionary = lpdf.copydictionary
+local pdfcopynumber = lpdf.copynumber
+local pdfcopyinteger = lpdf.copyinteger
+local pdfcopystring = lpdf.copystring
+local pdfcopyconstant = lpdf.copyconstant
-local nameonly = file.nameonly
+local pdfgetpos = lpdf.getpos
-local variables = interfaces.variables
-local codeinjections = backends.pdf.codeinjections
------ urlescaper = lpegpatterns.urlescaper
------ utftohigh = lpegpatterns.utftohigh
-local escapetex = characters.filters.utf.private.escape
+local hpack_node = nodes.hpack
-local bookmarks = structures.bookmarks
+local epdf = epdf
+local backends = backends
+local lpdf = lpdf
+local context = context
-local maxdimen = 0x3FFFFFFF -- 2^30-1
+local loadpdffile = lpdf.epdf.load
+
+local nameonly = file.nameonly
+
+local variables = interfaces.variables
+local codeinjections = backends.pdf.codeinjections
+----- urlescaper = lpegpatterns.urlescaper
+----- utftohigh = lpegpatterns.utftohigh
+local escapetex = characters.filters.utf.private.escape
+
+local bookmarks = structures.bookmarks
+
+local maxdimen = 0x3FFFFFFF -- 2^30-1
+
+local bpfactor = number.dimenfactors.bp
local layerspec = { -- predefining saves time
- "epdflinks"
+ "epdfcontent"
}
local collected = allocate()
@@ -66,6 +91,68 @@ end
job.register('job.embedded.collected',tobesaved,initializer)
+local function validdocument(specification)
+ if figures and not specification then
+ specification = figures and figures.current()
+ specification = specification and specification.status
+ end
+ if specification then
+ local fullname = specification.fullname
+ local expanded = lower(expandname(fullname))
+ -- we could add a check for duplicate page insertion
+ tobesaved[expanded] = true
+ --- but that is messy anyway so we forget about it
+ return specification, fullname, loadpdffile(fullname) -- costs time
+ end
+end
+
+local function getmediasize(specification,pagedata)
+ local xscale = specification.xscale or 1
+ local yscale = specification.yscale or 1
+ ----- size = specification.size or "crop" -- todo
+ local mediabox = pagedata.MediaBox
+ local llx = mediabox[1]
+ local lly = mediabox[2]
+ local urx = mediabox[3]
+ local ury = mediabox[4]
+ local width = xscale * (urx - llx) -- \\overlaywidth, \\overlayheight
+ local height = yscale * (ury - lly) -- \\overlaywidth, \\overlayheight
+ return llx, lly, urx, ury, width, height, xscale, yscale
+end
+
+local function getdimensions(annotation,llx,lly,xscale,yscale,width,height,report)
+ local rectangle = annotation.Rect
+ local a_llx = rectangle[1]
+ local a_lly = rectangle[2]
+ local a_urx = rectangle[3]
+ local a_ury = rectangle[4]
+ local x = xscale * (a_llx - llx)
+ local y = yscale * (a_lly - lly)
+ local w = xscale * (a_urx - a_llx)
+ local h = yscale * (a_ury - a_lly)
+ if w > width or h > height or w < 0 or h < 0 or abs(x) > (maxdimen/2) or abs(y) > (maxdimen/2) then
+ report("broken rectangle [%.6F %.6F %.6F %.6F] (max: %.6F)",a_llx,a_lly,a_urx,a_ury,maxdimen/2)
+ return
+ end
+ return x, y, w, h, a_llx, a_lly, a_urx, a_ury
+end
+
+local layerused = false
+
+local function initializelayer(height,width)
+ if not layerused then
+ context.definelayer(layerspec, { height = height .. "bp", width = width .. "bp" })
+ layerused = true
+ end
+end
+
+function codeinjections.flushmergelayer()
+ if layerused then
+ context.flushlayer(layerspec)
+ layerused = false
+ end
+end
+
local f_namespace = formatters["lpdf-epa-%s-"]
local function makenamespace(filename)
@@ -182,79 +269,48 @@ local function link_file(x,y,w,h,document,annotation)
end
end
+-- maybe handler per subtype and then one loop but then what about order ...
+
function codeinjections.mergereferences(specification)
- if figures and not specification then
- specification = figures and figures.current()
- specification = specification and specification.status
- end
- if not specification then
- return ""
- end
- local fullname = specification.fullname
- local expanded = lower(expandname(fullname))
- -- we could add a check for duplicate page insertion
- tobesaved[expanded] = true
- --- but that is messy anyway so we forget about it
- local document = loadpdffile(fullname) -- costs time
+ local specification, fullname, document = validdocument(specification)
if not document then
return ""
end
- local pagenumber = specification.page or 1
- local xscale = specification.yscale or 1
- local yscale = specification.yscale or 1
- local size = specification.size or "crop" -- todo
+ local pagenumber = specification.page or 1
local pagedata = document.pages[pagenumber]
local annotations = pagedata and pagedata.Annots
local namespace = makenamespace(fullname)
local reference = namespace .. pagenumber
if annotations and annotations.n > 0 then
- local mediabox = pagedata.MediaBox
- local llx = mediabox[1]
- local lly = mediabox[2]
- local urx = mediabox[3]
- local ury = mediabox[4]
- local width = xscale * (urx - llx) -- \\overlaywidth, \\overlayheight
- local height = yscale * (ury - lly) -- \\overlaywidth, \\overlayheight
- context.definelayer( { "epdflinks" }, { height = height.."bp" , width = width.."bp" })
+ local llx, lly, urx, ury, width, height, xscale, yscale = getmediasize(specification,pagedata,xscale,yscale)
+ initializelayer(height,width)
for i=1,annotations.n do
local annotation = annotations[i]
if annotation then
- local subtype = annotation.Subtype
- local rectangle = annotation.Rect
- local a_llx = rectangle[1]
- local a_lly = rectangle[2]
- local a_urx = rectangle[3]
- local a_ury = rectangle[4]
- local x = xscale * (a_llx - llx)
- local y = yscale * (a_lly - lly)
- local w = xscale * (a_urx - a_llx)
- local h = yscale * (a_ury - a_lly)
- if subtype == "Link" then
+ if annotation.Subtype == "Link" then
local a = annotation.A
if not a then
report_link("missing link annotation")
- elseif w > width or h > height or w < 0 or h < 0 or abs(x) > (maxdimen/2) or abs(y) > (maxdimen/2) then
- report_link("broken link rectangle [%.6F %.6F %.6F %.6F] (max: %.6F)",a_llx,a_lly,a_urx,a_ury,maxdimen/2)
else
- local linktype = a.S
- if linktype == "GoTo" then
- link_goto(x,y,w,h,document,annotation,pagedata,namespace)
- elseif linktype == "GoToR" then
- link_file(x,y,w,h,document,annotation)
- elseif linktype == "URI" then
- link_uri(x,y,w,h,document,annotation)
- elseif trace_links then
- report_link("unsupported link annotation %a",linktype)
+ local x, y, w, h = getdimensions(annotation,llx,lly,xscale,yscale,width,height,report_link)
+ if x then
+ local linktype = a.S
+ if linktype == "GoTo" then
+ link_goto(x,y,w,h,document,annotation,pagedata,namespace)
+ elseif linktype == "GoToR" then
+ link_file(x,y,w,h,document,annotation)
+ elseif linktype == "URI" then
+ link_uri(x,y,w,h,document,annotation)
+ elseif trace_links then
+ report_link("unsupported link annotation %a",linktype)
+ end
end
end
- elseif trace_links then
- report_link("unsupported annotation %a",subtype)
end
elseif trace_links then
report_link("broken annotation, index %a",i)
end
end
- context.flushlayer { "epdflinks" }
end
-- moved outside previous test
context.setgvalue("figurereference",reference) -- global
@@ -270,43 +326,520 @@ function codeinjections.mergeviewerlayers(specification)
if true then
return
end
- if not specification then
- specification = figures and figures.current()
- specification = specification and specification.status
+ local specification, fullname, document = validdocument(specification)
+ if not document then
+ return ""
end
- if specification then
- local fullname = specification.fullname
- local document = loadpdffile(fullname)
- if document then
- local namespace = makenamespace(fullname)
- local layers = document.layers
- if layers then
- for i=1,layers.n do
- local layer = layers[i]
- if layer then
- local tag = namespace .. gsub(layer," ",":")
- local title = tag
- if trace_links then
- report_link("using layer %a",tag)
- end
- attributes.viewerlayers.define { -- also does some cleaning
- tag = tag, -- todo: #3A or so
- title = title,
- visible = variables.start,
- editable = variables.yes,
- printable = variables.yes,
- }
- codeinjections.useviewerlayer(tag)
- elseif trace_links then
- report_link("broken layer, index %a",i)
- end
+ local namespace = makenamespace(fullname)
+ local layers = document.layers
+ if layers then
+ for i=1,layers.n do
+ local layer = layers[i]
+ if layer then
+ local tag = namespace .. gsub(layer," ",":")
+ local title = tag
+ if trace_links then
+ report_link("using layer %a",tag)
end
+ attributes.viewerlayers.define { -- also does some cleaning
+ tag = tag, -- todo: #3A or so
+ title = title,
+ visible = variables.start,
+ editable = variables.yes,
+ printable = variables.yes,
+ }
+ codeinjections.useviewerlayer(tag)
+ elseif trace_links then
+ report_link("broken layer, index %a",i)
end
end
end
end
--- new: for taco
+-- It took a bit of puzzling and playing around to come to the following
+-- implementation. In the end it looks simple but as usual it takes a while
+-- to see what the specification (and implementation) boils down to. Lots of
+-- shared properties and such. The scaling took some trial and error as
+-- viewers differ. I had to extend some low level helpers to make it more
+-- comfortable. Hm, the specification is somewhat incomplete as some fields
+-- are permitted even if not mentioned so in the end we can share more code.
+--
+-- If all works ok, we can get rid of some copies which saves time and space.
+
+local commentlike = {
+ Text = "text",
+ FreeText = "freetext",
+ Line = "line",
+ Square = "shape",
+ Circle = "shape",
+ Polygon = "poly",
+ PolyLine = "poly",
+ Highlight = "markup",
+ Underline = "markup",
+ Squiggly = "markup",
+ StrikeOut = "markup",
+ Caret = "text",
+ Stamp = "stamp",
+ Ink = "ink",
+ Popup = "popup",
+}
+
+local function copyBS(v) -- dict can be shared
+ if v then
+ -- return pdfdictionary {
+ -- Type = copypdfconstant(V.Type),
+ -- W = copypdfnumber (V.W),
+ -- S = copypdfstring (V.S),
+ -- D = copypdfarray (V.D),
+ -- }
+ return copypdfdictionary(v)
+ end
+end
+
+local function copyBE(v) -- dict can be shared
+ if v then
+ -- return pdfdictionary {
+ -- S = copypdfstring(V.S),
+ -- I = copypdfnumber(V.I),
+ -- }
+ return copypdfdictionary(v)
+ end
+end
+
+local function copyBorder(v) -- dict can be shared
+ if v then
+ -- todo
+ return copypdfarray(v)
+ end
+end
+
+local function copyPopup(v,references)
+ if v then
+ local p = references[v]
+ if p then
+ return pdfreference(p)
+ end
+ end
+end
+
+local function copyParent(v,references)
+ if v then
+ local p = references[v]
+ if p then
+ return pdfreference(p)
+ end
+ end
+end
+
+local function copyIRT(v,references)
+ if v then
+ local p = references[v]
+ if p then
+ return pdfreference(p)
+ end
+ end
+end
+
+local function copyC(v)
+ if v then
+ -- todo: check color space
+ return pdfcopyarray(v)
+ end
+end
+
+local function finalizer(d,xscale,yscale,a_llx,a_ury)
+ local q = d.QuadPoints or d.Vertices or d.CL
+ if q then
+ return function()
+ local h, v = pdfgetpos() -- already scaled
+ for i=1,#q,2 do
+ q[i] = xscale * q[i] + (h*bpfactor - xscale * a_llx)
+ q[i+1] = yscale * q[i+1] + (v*bpfactor - yscale * a_ury)
+ end
+ return d()
+ end
+ end
+ q = d.InkList or d.Path
+ if q then
+ return function()
+ local h, v = pdfgetpos() -- already scaled
+ for i=1,#q do
+ local q = q[i]
+ for i=1,#q,2 do
+ q[i] = xscale * q[i] + (h*bpfactor - xscale * a_llx)
+ q[i+1] = yscale * q[i+1] + (v*bpfactor - yscale * a_ury)
+ end
+ end
+ return d()
+ end
+ end
+ return d()
+end
+
+local validstamps = {
+ Approved = true,
+ Experimental = true,
+ NotApproved = true,
+ AsIs = true,
+ Expired = true,
+ NotForPublicRelease = true,
+ Confidential = true,
+ Final = true,
+ Sold = true,
+ Departmental = true,
+ ForComment = true,
+ TopSecret = true,
+ Draft = true,
+ ForPublicRelease = true,
+}
+
+local function validStamp(v)
+ local name = "Stamped" -- fallback
+ if v then
+ local ok = validstamps[v]
+ if ok then
+ name = ok
+ else
+ for k in next, validstamps do
+ if find(v,k.."$") then
+ name = k
+ validstamps[v] = k
+ break
+ end
+ end
+ end
+ end
+ -- we temporary return to \TEX:
+ context.predefinesymbol { name }
+ context.step()
+ -- beware, an error is not reported
+ return pdfconstant(name), codeinjections.analyzenormalsymbol(name)
+end
+
+local annotationflags = lpdf.flags.annotations
+
+local function copyF(v,lock) -- todo: bxor 24
+ if lock then
+ v = bor(v or 0,annotationflags.ReadOnly + annotationflags.Locked + annotationflags.LockedContents)
+ end
+ if v then
+ return pdfcopyinteger(v)
+ end
+end
+
+-- Speed is not really an issue so we don't optimize this code too much. In the end (after
+-- testing we end up with less code that we started with.
+
+function codeinjections.mergecomments(specification)
+ -- local specification, fullname, document = validdocument(specification)
+ -- if not document then
+ -- return ""
+ -- end
+ -- local pagenumber = specification.page or 1
+ -- local pagedata = document.pages[pagenumber]
+ -- local annotations = pagedata and pagedata.Annots
+ -- if annotations and annotations.n > 0 then
+ -- local llx, lly, urx, ury, width, height, xscale, yscale = getmediasize(specification,pagedata,xscale,yscale)
+ -- initializelayer(height,width)
+ -- --
+ -- local lockflags = specification.lock -- todo: proper parameter
+ -- local references = { }
+ -- local usedpopups = { }
+ -- for i=1,annotations.n do
+ -- local annotation = annotations[i]
+ -- if annotation then
+ -- local subtype = annotation.Subtype
+ -- if commentlike[subtype] then
+ -- references[annotation] = pdfreserveobject()
+ -- local p = annotation.Popup
+ -- if p then
+ -- usedpopups[p] = true
+ -- end
+ -- end
+ -- end
+ -- end
+ -- --
+ -- for i=1,annotations.n do
+ -- -- we keep the order
+ -- local annotation = annotations[i]
+ -- if annotation then
+ -- local reference = references[annotation]
+ -- if reference then
+ -- local subtype = annotation.Subtype
+ -- local kind = commentlike[subtype]
+ -- if kind ~= "popup" or usedpopups[annotation] then
+ -- local x, y, w, h, a_llx, a_lly, a_urx, a_ury = getdimensions(annotation,llx,lly,xscale,yscale,width,height,report_comment)
+ -- if x then
+ -- local voffset = h
+ -- local dictionary = pdfdictionary {
+ -- Subtype = pdfconstant (subtype),
+ -- -- common (skipped: P AP AS OC AF BM StructParent)
+ -- Contents = pdfcopyunicode(annotation.Contents),
+ -- NM = pdfcopystring (annotation.NM),
+ -- M = pdfcopystring (annotation.M),
+ -- F = copyF (annotation.F,lockflags),
+ -- C = copyC (annotation.C),
+ -- ca = pdfcopynumber (annotation.ca),
+ -- CA = pdfcopynumber (annotation.CA),
+ -- Lang = pdfcopystring (annotation.Lang),
+ -- -- also common
+ -- CreationDate = pdfcopystring (annotation.CreationDate),
+ -- T = pdfcopyunicode(annotation.T),
+ -- Subj = pdfcopyunicode(annotation.Subj),
+ -- -- border
+ -- Border = pdfcopyarray (annotation.Border),
+ -- BS = copyBS (annotation.BS),
+ -- BE = copyBE (annotation.BE),
+ -- -- sort of common
+ -- Popup = copyPopup (annotation.Popup,references),
+ -- RC = pdfcopyunicode(annotation.RC) -- string or stream
+ -- }
+ -- if kind == "markup" then
+ -- dictionary.IRT = copyIRT (annotation.IRT,references)
+ -- dictionary.RT = pdfconstant (annotation.RT)
+ -- dictionary.IT = pdfcopyconstant (annotation.IT)
+ -- dictionary.QuadPoints = pdfcopyarray (annotation.QuadPoints)
+ -- -- dictionary.RD = pdfcopyarray (annotation.RD)
+ -- elseif kind == "text" then
+ -- -- somehow F fails to view : /F 24 : bit4=nozoom bit5=norotate
+ -- dictionary.F = nil
+ -- dictionary.Open = pdfcopyboolean (annotation.Open)
+ -- dictionary.Name = pdfcopyunicode (annotation.Name)
+ -- dictionary.State = pdfcopystring (annotation.State)
+ -- dictionary.StateModel = pdfcopystring (annotation.StateModel)
+ -- dictionary.IT = pdfcopyconstant (annotation.IT)
+ -- dictionary.QuadPoints = pdfcopyarray (annotation.QuadPoints)
+ -- dictionary.RD = pdfcopyarray (annotation.RD) -- caret
+ -- dictionary.Sy = pdfcopyconstant (annotation.Sy) -- caret
+ -- voffset = 0
+ -- elseif kind == "freetext" then
+ -- dictionary.DA = pdfcopystring (annotation.DA)
+ -- dictionary.Q = pdfcopyinteger (annotation.Q)
+ -- dictionary.DS = pdfcopystring (annotation.DS)
+ -- dictionary.CL = pdfcopyarray (annotation.CL)
+ -- dictionary.IT = pdfcopyconstant (annotation.IT)
+ -- dictionary.LE = pdfcopyconstant (annotation.LE)
+ -- -- dictionary.RC = pdfcopystring (annotation.RC)
+ -- elseif kind == "line" then
+ -- dictionary.LE = pdfcopyarray (annotation.LE)
+ -- dictionary.IC = pdfcopyarray (annotation.IC)
+ -- dictionary.LL = pdfcopynumber (annotation.LL)
+ -- dictionary.LLE = pdfcopynumber (annotation.LLE)
+ -- dictionary.Cap = pdfcopyboolean (annotation.Cap)
+ -- dictionary.IT = pdfcopyconstant (annotation.IT)
+ -- dictionary.LLO = pdfcopynumber (annotation.LLO)
+ -- dictionary.CP = pdfcopyconstant (annotation.CP)
+ -- dictionary.Measure = pdfcopydictionary(annotation.Measure) -- names
+ -- dictionary.CO = pdfcopyarray (annotation.CO)
+ -- voffset = 0
+ -- elseif kind == "shape" then
+ -- dictionary.IC = pdfcopyarray (annotation.IC)
+ -- -- dictionary.RD = pdfcopyarray (annotation.RD)
+ -- voffset = 0
+ -- elseif kind == "stamp" then
+ -- local name, appearance = validStamp(annotation.Name)
+ -- dictionary.Name = name
+ -- dictionary.AP = appearance
+ -- voffset = 0
+ -- elseif kind == "ink" then
+ -- dictionary.InkList = pdfcopyarray (annotation.InkList)
+ -- elseif kind == "poly" then
+ -- dictionary.Vertices = pdfcopyarray (annotation.Vertices)
+ -- -- dictionary.LE = pdfcopyarray (annotation.LE) -- todo: names in array
+ -- dictionary.IC = pdfcopyarray (annotation.IC)
+ -- dictionary.IT = pdfcopyconstant (annotation.IT)
+ -- dictionary.Measure = pdfcopydictionary(annotation.Measure)
+ -- dictionary.Path = pdfcopyarray (annotation.Path)
+ -- -- dictionary.RD = pdfcopyarray (annotation.RD)
+ -- elseif kind == "popup" then
+ -- dictionary.Open = pdfcopyboolean (annotation.Open)
+ -- dictionary.Parent = copyParent (annotation.Parent,references)
+ -- voffset = 0
+ -- end
+ -- if dictionary then
+ -- local locationspec = {
+ -- x = x .. "bp",
+ -- y = y .. "bp",
+ -- voffset = voffset .. "bp",
+ -- preset = "leftbottom",
+ -- }
+ -- local finalize = finalizer(dictionary,xscale,yscale,a_llx,a_ury)
+ -- context.setlayer(layerspec,locationspec,function()
+ -- context(hpack_node(nodeinjections.annotation(w/bpfactor,h/bpfactor,0,finalize,reference)))
+ -- end)
+ -- end
+ -- end
+ -- else
+ -- -- report_comment("skipping annotation, index %a",i)
+ -- end
+ -- end
+ -- elseif trace_comments then
+ -- report_comment("broken annotation, index %a",i)
+ -- end
+ -- end
+ -- end
+ -- return namespace
+end
+
+local widgetflags = lpdf.flags.widgets
+
+local function flagstoset(flag,flags)
+ local t = { }
+ if flags then
+ for k, v in next, flags do
+ if band(flag,v) ~= 0 then
+ t[k] = true
+ end
+ end
+ end
+ return t
+end
+
+-- BS : border style dict
+-- R : rotation 0 90 180 270
+-- BG : background array
+-- CA : caption string
+-- RC : roll over caption
+-- AC : down caption
+-- I/RI/IX : icon streams
+-- IF : fit dictionary
+-- TP : text position number
+
+-- Opt : array of texts
+-- TI : top index
+
+-- V : value
+-- DV : default value
+-- DS : default string
+-- RV : rich
+-- Q : quadding (0=left 1=middle 2=right)
+
+function codeinjections.mergefields(specification)
+ -- local specification, fullname, document = validdocument(specification)
+ -- if not document then
+ -- return ""
+ -- end
+ -- local pagenumber = specification.page or 1
+ -- local pagedata = document.pages[pagenumber]
+ -- local annotations = pagedata and pagedata.Annots
+ -- if annotations and annotations.n > 0 then
+ -- local llx, lly, urx, ury, width, height, xscale, yscale = getmediasize(specification,pagedata,xscale,yscale)
+ -- initializelayer(height,width)
+ -- --
+ -- for i=1,annotations.n do
+ -- -- we keep the order
+ -- local annotation = annotations[i]
+ -- if annotation then
+ -- local subtype = annotation.Subtype
+ -- if subtype == "Widget" then
+ -- local parent = annotation.Parent or { }
+ -- local name = annotation.T or parent.T
+ -- local what = annotation.FT or parent.FT
+ -- if name and what then
+ -- local x, y, w, h, a_llx, a_lly, a_urx, a_ury = getdimensions(annotation,llx,lly,xscale,yscale,width,height,report_field)
+ -- if x then
+ -- x = x .. "bp"
+ -- y = y .. "bp"
+ -- local W, H = w, h
+ -- w = w .. "bp"
+ -- h = h .. "bp"
+ -- if trace_fields then
+ -- report_field("field %a, type %a, dx %s, dy %s, wd %s, ht %s",name,what,x,y,w,h)
+ -- end
+ -- local locationspec = {
+ -- x = x,
+ -- y = y,
+ -- preset = "leftbottom",
+ -- }
+ -- --
+ -- local aflags = flagstoset(annotation.F or parent.F, annotationflags)
+ -- local wflags = flagstoset(annotation.Ff or parent.Ff, widgetflags)
+ -- if what == "Tx" then
+ -- -- DA DV F FT MaxLen MK Q T V | AA OC
+ -- if wflags.MultiLine then
+ -- wflags.MultiLine = nil
+ -- what = "text"
+ -- else
+ -- what = "line"
+ -- end
+ -- -- via context
+ -- local fieldspec = {
+ -- width = w,
+ -- height = h,
+ -- offset = variables.overlay,
+ -- frame = trace_links and variables.on or variables.off,
+ -- n = annotation.MaxLen or (parent and parent.MaxLen),
+ -- type = what,
+ -- option = concat(merged(aflags,wflags),","),
+ -- }
+ -- context.setlayer (layerspec,locationspec,function()
+ -- context.definefieldbody ( { name } , fieldspec )
+ -- context.fieldbody ( { name } )
+ -- end)
+ -- --
+ -- elseif what == "Btn" then
+ -- if wflags.Radio or wflags.RadiosInUnison then
+ -- -- AP AS DA F Ff FT H MK T V | AA OC
+ -- wflags.Radio = nil
+ -- wflags.RadiosInUnison = nil
+ -- what = "radio"
+ -- elseif wflags.PushButton then
+ -- -- AP DA F Ff FT H MK T | AA OC
+ -- --
+ -- -- Push buttons only have an appearance and some associated
+ -- -- actions so they are not worth copying.
+ -- --
+ -- wflags.PushButton = nil
+ -- what = "push"
+ -- else
+ -- -- AP AS DA F Ff FT H MK T V | OC AA
+ -- what = "check"
+ -- -- direct
+ -- local AP = annotation.AP or (parent and parent.AP)
+ -- if AP then
+ -- local im = img.new { filename = fullname }
+ -- AP = img.immediatewriteobject(im,document.__xrefs__[AP])
+ -- end
+ -- local dictionary = pdfdictionary {
+ -- Subtype = pdfconstant("Widget"),
+ -- FT = pdfconstant("Btn"),
+ -- T = pdfcopyunicode(annotation.T or parent.T),
+ -- F = pdfcopyinteger(annotation.F or parent.F),
+ -- Ff = pdfcopyinteger(annotation.Ff or parent.Ff),
+ -- AS = pdfcopyconstant(annotation.AS or (parent and parent.AS)),
+ -- AP = AP and pdfreference(AP),
+ -- }
+ -- local finalize = dictionary()
+ -- context.setlayer(layerspec,locationspec,function()
+ -- context(hpack_node(nodeinjections.annotation(W/bpfactor,H/bpfactor,0,finalize)))
+ -- end)
+ -- --
+ -- end
+ -- elseif what == "Ch" then
+ -- -- F Ff FT Opt T | AA OC (rest follows)
+ -- if wflags.PopUp then
+ -- wflags.PopUp = nil
+ -- if wflags.Edit then
+ -- wflags.Edit = nil
+ -- what = "combo"
+ -- else
+ -- what = "popup"
+ -- end
+ -- else
+ -- what = "choice"
+ -- end
+ -- elseif what == "Sig" then
+ -- what = "signature"
+ -- else
+ -- what = nil
+ -- end
+ -- end
+ -- end
+ -- end
+ -- end
+ -- end
+ -- end
+end
-- Beware, bookmarks can be in pdfdoc encoding or in unicode. However, in mkiv we
-- write out the strings in unicode (hex). When we read them in, we check for a bom
@@ -471,16 +1004,6 @@ function codeinjections.mergebookmarks(specification)
end
end
--- placeholders:
-
-function codeinjections.mergecomments(specification)
- report_comment("unfinished experimental code, not used yet")
-end
-
-function codeinjections.mergefields(specification)
- report_field("unfinished experimental code, not used yet")
-end
-
-- A bit more than a placeholder but in the same perspective as
-- inclusion of comments and fields:
--