From f58a2cb5d22c5931581274db1f0ec85ac903b747 Mon Sep 17 00:00:00 2001 From: Hans Hagen Date: Mon, 28 Oct 2019 20:03:50 +0100 Subject: 2019-10-28 18:22:00 --- tex/context/base/mkiv/lpdf-ano.lua | 188 +++++++++++++++++++------------------ 1 file changed, 95 insertions(+), 93 deletions(-) (limited to 'tex/context/base/mkiv/lpdf-ano.lua') diff --git a/tex/context/base/mkiv/lpdf-ano.lua b/tex/context/base/mkiv/lpdf-ano.lua index 05f18f512..1c4a3ba27 100644 --- a/tex/context/base/mkiv/lpdf-ano.lua +++ b/tex/context/base/mkiv/lpdf-ano.lua @@ -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") -- cgit v1.2.3