summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/context/base/mkiv/lpdf-ano.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/context/base/mkiv/lpdf-ano.lua')
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lpdf-ano.lua268
1 files changed, 144 insertions, 124 deletions
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-ano.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-ano.lua
index 49bf973c9f8..c04ada15156 100644
--- a/Master/texmf-dist/tex/context/base/mkiv/lpdf-ano.lua
+++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-ano.lua
@@ -18,7 +18,7 @@ local rep, format, find = string.rep, string.format, string.find
local min = math.min
local lpegmatch = lpeg.match
local formatters = string.formatters
-local sortedkeys = table.sortedkeys
+local sortedkeys, concat = table.sortedkeys, table.concat
local backends, lpdf = backends, lpdf
@@ -93,7 +93,7 @@ local pdfrectangle = lpdf.rectangle
-- todo: 3dview
-local pdf_annot = pdfconstant("Annot")
+----- pdf_annot = pdfconstant("Annot")
local pdf_uri = pdfconstant("URI")
local pdf_gotor = pdfconstant("GoToR")
local pdf_goto = pdfconstant("GoTo")
@@ -133,6 +133,99 @@ local function checkautoprefixes(destinations)
end
end
+local maxslice = 32 -- could be made configureable ... 64 is also ok
+
+local function pdfmakenametree(list,apply)
+ if not next(list) then
+ return
+ end
+ local slices = { }
+ local sorted = sortedkeys(list)
+ local size = #sorted
+ local maxslice = maxslice
+ if size <= 1.5*maxslice then
+ maxslice = size
+ end
+ for i=1,size,maxslice do
+ local amount = min(i+maxslice-1,size)
+ local names = pdfarray { }
+ local n = 0
+ for j=i,amount do
+ local name = sorted[j]
+ local target = list[name]
+ n = n + 1 ; names[n] = tostring(name)
+ n = n + 1 ; names[n] = apply and apply(target) or target
+ end
+ local first = sorted[i]
+ local last = sorted[amount]
+ local limits = pdfarray {
+ first,
+ last,
+ }
+ local d = pdfdictionary {
+ Names = names,
+ Limits = limits,
+ }
+ slices[#slices+1] = {
+ reference = pdfreference(pdfflushobject(d)),
+ limits = limits,
+ }
+ end
+ local function collectkids(slices,first,last)
+ local f = slices[first]
+ local l = slices[last]
+ if f and l then
+ local k = pdfarray()
+ local n = 0
+ local d = pdfdictionary {
+ Kids = k,
+ Limits = pdfarray {
+ f.limits[1],
+ l.limits[2],
+ },
+ }
+ for i=first,last do
+ n = n + 1 ; k[n] = slices[i].reference
+ end
+ return d
+ end
+ end
+ if #slices == 1 then
+ return slices[1].reference
+ else
+ while true do
+ local size = #slices
+ if size > maxslice then
+ local temp = { }
+ local n = 0
+ for i=1,size,maxslice do
+ local kids = collectkids(slices,i,min(i+maxslice-1,size))
+ if kids then
+ n = n + 1
+ temp[n] = {
+ reference = pdfreference(pdfflushobject(kids)),
+ limits = kids.Limits,
+ }
+ else
+ -- error
+ end
+ end
+ slices = temp
+ else
+ local kids = collectkids(slices,1,size)
+ if kids then
+ return pdfreference(pdfflushobject(kids))
+ else
+ -- error
+ return
+ end
+ end
+ end
+ end
+end
+
+lpdf.makenametree = pdfmakenametree
+
-- Bah, I hate this kind of features .. anyway, as we have delayed resolving we
-- only support a document-wide setup and it has to be set before the first one
-- is used. Also, we default to a non-intrusive gray and the outline is kept
@@ -237,8 +330,6 @@ end
lpdf.registerdestination = pdfregisterdestination
-local maxslice = 32 -- could be made configureable ... 64 is also ok
-
logs.registerfinalactions(function()
if log_destinations and next(destinations) then
local report = logs.startfilelogging("references","used destinations")
@@ -252,98 +343,10 @@ logs.registerfinalactions(function()
end
end)
-local function pdfnametree(destinations)
- local slices = { }
- checkautoprefixes(destinations)
- if not next(destinations) then
- return
- end
- local sorted = sortedkeys(destinations)
- local size = #sorted
-
- if size <= 1.5*maxslice then
- maxslice = size
- end
-
- for i=1,size,maxslice do
- local amount = min(i+maxslice-1,size)
- local names = pdfarray { }
- local n = 0
- for j=i,amount do
- local destination = sorted[j]
- local pagenumber = destinations[destination]
- n = n + 1 ; names[n] = tostring(destination) -- tostring is a safeguard
- n = n + 1 ; names[n] = pdfreference(pagenumber)
- end
- local first = sorted[i]
- local last = sorted[amount]
- local limits = pdfarray {
- first,
- last,
- }
- local d = pdfdictionary {
- Names = names,
- Limits = limits,
- }
- slices[#slices+1] = {
- reference = pdfreference(pdfflushobject(d)),
- limits = limits,
- }
- end
- local function collectkids(slices,first,last)
- local f = slices[first]
- local l = slices[last]
- if f and l then
- local k = pdfarray()
- local n = 0
- local d = pdfdictionary {
- Kids = k,
- Limits = pdfarray {
- f.limits[1],
- l.limits[2],
- },
- }
- for i=first,last do
- n = n + 1 ; k[n] = slices[i].reference
- end
- return d
- end
- end
- if #slices == 1 then
- return slices[1].reference
- else
- while true do
- if #slices > maxslice then
- local temp = { }
- local size = #slices
- for i=1,size,maxslice do
- local kids = collectkids(slices,i,min(i+maxslice-1,size))
- if kids then
- temp[#temp+1] = {
- reference = pdfreference(pdfflushobject(kids)),
- limits = kids.Limits,
- }
- else
- -- error
- end
- end
- slices = temp
- else
- local kids = collectkids(slices,1,#slices)
- if kids then
- return pdfreference(pdfflushobject(kids))
- else
- -- error
- return
- end
- end
- end
- end
-end
-
local function pdfdestinationspecification()
if next(destinations) then -- safeguard
- local r = pdfnametree(destinations)
+ checkautoprefixes(destinations)
+ local r = pdfmakenametree(destinations,pdfreference)
if r then
pdfaddtonames("Dests",r)
end
@@ -353,7 +356,6 @@ local function pdfdestinationspecification()
end
end
-lpdf.nametree = pdfnametree
lpdf.destinationspecification = pdfdestinationspecification
lpdf.registerdocumentfinalizer(pdfdestinationspecification,"collect destinations")
@@ -362,25 +364,14 @@ lpdf.registerdocumentfinalizer(pdfdestinationspecification,"collect destinations
local destinations = { }
-local f_xyz = formatters["<< /D [ %i 0 R /XYZ %.6F %.6F null ] >>"]
+local f_xyz = formatters["<< /D [ %i 0 R /XYZ %.6N %.6N null ] >>"]
local f_fit = formatters["<< /D [ %i 0 R /Fit ] >>"]
local f_fitb = formatters["<< /D [ %i 0 R /FitB ] >>"]
-local f_fith = formatters["<< /D [ %i 0 R /FitH %.6F ] >>"]
-local f_fitv = formatters["<< /D [ %i 0 R /FitV %.6F ] >>"]
-local f_fitbh = formatters["<< /D [ %i 0 R /FitBH %.6F ] >>"]
-local f_fitbv = formatters["<< /D [ %i 0 R /FitBV %.6F ] >>"]
-local f_fitr = formatters["<< /D [ %i 0 R /FitR %.6F %.6F %.6F %.6F ] >>"]
-
-directives.register("pdf.stripzeros",function()
- f_xyz = formatters["<< /D [ %i 0 R /XYZ %.6N %.6N null ] >>"]
- f_fit = formatters["<< /D [ %i 0 R /Fit ] >>"]
- f_fitb = formatters["<< /D [ %i 0 R /FitB ] >>"]
- f_fith = formatters["<< /D [ %i 0 R /FitH %.6N ] >>"]
- f_fitv = formatters["<< /D [ %i 0 R /FitV %.6N ] >>"]
- f_fitbh = formatters["<< /D [ %i 0 R /FitBH %.6N ] >>"]
- f_fitbv = formatters["<< /D [ %i 0 R /FitBV %.6N ] >>"]
- f_fitr = formatters["<< /D [ %i 0 R /FitR %.6N %.6N %.6N %.6N ] >>"]
-end)
+local f_fith = formatters["<< /D [ %i 0 R /FitH %.6N ] >>"]
+local f_fitv = formatters["<< /D [ %i 0 R /FitV %.6N ] >>"]
+local f_fitbh = formatters["<< /D [ %i 0 R /FitBH %.6N ] >>"]
+local f_fitbv = formatters["<< /D [ %i 0 R /FitBV %.6N ] >>"]
+local f_fitr = formatters["<< /D [ %i 0 R /FitR %.6N %.6N %.6N %.6N ] >>"]
local v_standard = variables.standard
local v_frame = variables.frame
@@ -634,9 +625,9 @@ local function pdffilelink(filename,destination,page,actions)
destination = pdfarray { (page or 1) - 1, pdf_fit }
end
return pdfdictionary {
- S = pdf_gotor, -- can also be pdf_launch
- F = filename,
- D = destination or defaultdestination,
+ S = pdf_gotor, -- can also be pdf_launch
+ F = filename,
+ D = destination or defaultdestination,
NewWindow = actions.newwindow and true or nil,
}
end
@@ -758,11 +749,8 @@ local nofused = 0
local nofspecial = 0
local share = true
-local f_annot = formatters["<< /Type /Annot %s /Rect [ %0.6F %0.6F %0.6F %0.6F ] >>"]
-
-directives.register("pdf.stripzeros",function()
- f_annot = formatters["<< /Type /Annot %s /Rect [ %0.6N %0.6N %0.6N %0.6N ] >>"]
-end)
+local f_annot = formatters["<< /Type /Annot %s /Rect [ %.6N %.6N %.6N %.6N ] >>"]
+local f_quadp = formatters["<< /Type /Annot %s /QuadPoints [ %s ] /Rect [ %.6N %.6N %.6N %.6N ] >>"]
directives.register("references.sharelinks", function(v)
share = v
@@ -777,10 +765,41 @@ setmetatableindex(hashed,function(t,k)
return v
end)
-local function finishreference(specification) -- %0.2f looks okay enough (no scaling anyway)
- local annot = hashed[f_annot(specification.prerolled,pdfrectangle(specification.width,specification.height,specification.depth))]
+local function toquadpoints(paths)
+ local t, n = { }, 0
+ for i=1,#paths do
+ local path = paths[i]
+ local size = #path
+ for j=1,size do
+ local p = path[j]
+ n = n + 1 ; t[n] = p[1]
+ n = n + 1 ; t[n] = p[2]
+ end
+ local m = size % 4
+ if m > 0 then
+ local p = path[size]
+ for j=size+1,m do
+ n = n + 1 ; t[n] = p[1]
+ n = n + 1 ; t[n] = p[2]
+ end
+ end
+ end
+ return concat(t," ")
+end
+
+local function finishreference(specification)
+ local prerolled = specification.prerolled
+ local quadpoints = specification.mesh
+ local llx, lly,
+ urx, ury = pdfrectangle(specification.width,specification.height,specification.depth)
+ local specifier = nil
+ if quadpoints and #quadpoints > 0 then
+ specifier = f_quadp(prerolled,toquadpoints(quadpoints),llx,lly,urx,ury)
+ else
+ specifier = f_annot(prerolled,llx,lly,urx,ury)
+ end
nofused = nofused + 1
- return pdfregisterannotation(annot)
+ return pdfregisterannotation(hashed[specifier])
end
local function finishannotation(specification)
@@ -799,7 +818,7 @@ local function finishannotation(specification)
return pdfregisterannotation(objref)
end
-function nodeinjections.reference(width,height,depth,prerolled)
+function nodeinjections.reference(width,height,depth,prerolled,mesh)
if prerolled then
if trace_references then
report_references("link: width %p, height %p, depth %p, prerolled %a",width,height,depth,prerolled)
@@ -810,6 +829,7 @@ function nodeinjections.reference(width,height,depth,prerolled)
height = height,
depth = depth,
prerolled = prerolled,
+ mesh = mesh,
}
end
end