summaryrefslogtreecommitdiff
path: root/tex/context/base/lpdf-ini.lua
diff options
context:
space:
mode:
authorContext Git Mirror Bot <phg42.2a@gmail.com>2016-01-12 17:15:07 +0100
committerContext Git Mirror Bot <phg42.2a@gmail.com>2016-01-12 17:15:07 +0100
commit8d8d528d2ad52599f11250cfc567fea4f37f2a8b (patch)
tree94286bc131ef7d994f9432febaf03fe23d10eef8 /tex/context/base/lpdf-ini.lua
parentf5aed2e51223c36c84c5f25a6cad238b2af59087 (diff)
downloadcontext-8d8d528d2ad52599f11250cfc567fea4f37f2a8b.tar.gz
2016-01-12 16:26:00
Diffstat (limited to 'tex/context/base/lpdf-ini.lua')
-rw-r--r--tex/context/base/lpdf-ini.lua1249
1 files changed, 0 insertions, 1249 deletions
diff --git a/tex/context/base/lpdf-ini.lua b/tex/context/base/lpdf-ini.lua
deleted file mode 100644
index 6bce56b43..000000000
--- a/tex/context/base/lpdf-ini.lua
+++ /dev/null
@@ -1,1249 +0,0 @@
-if not modules then modules = { } end modules ['lpdf-ini'] = {
- version = 1.001,
- comment = "companion to lpdf-ini.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- beware of "too many locals" here
-
-local setmetatable, getmetatable, type, next, tostring, tonumber, rawset = setmetatable, getmetatable, type, next, tostring, tonumber, rawset
-local char, byte, format, gsub, concat, match, sub, gmatch = string.char, string.byte, string.format, string.gsub, table.concat, string.match, string.sub, string.gmatch
-local utfchar, utfbyte, utfvalues = utf.char, utf.byte, utf.values
-local sind, cosd, floor, max, min = math.sind, math.cosd, math.floor, math.max, math.min
-local lpegmatch, P, C, R, S, Cc, Cs = lpeg.match, lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.Cc, lpeg.Cs
-local formatters = string.formatters
-local isboolean = string.is_boolean
-
-local report_objects = logs.reporter("backend","objects")
-local report_finalizing = logs.reporter("backend","finalizing")
-local report_blocked = logs.reporter("backend","blocked")
-
-local implement = interfaces.implement
-local two_strings = interfaces.strings[2]
-
--- In ConTeXt MkIV we use utf8 exclusively so all strings get mapped onto a hex
--- encoded utf16 string type between <>. We could probably save some bytes by using
--- strings between () but then we end up with escaped ()\ too.
-
--- gethpos : used
--- getpos : used
--- getvpos : used
---
--- getmatrix : used
--- hasmatrix : used
---
--- mapfile : used in font-ctx.lua
--- mapline : used in font-ctx.lua
---
--- maxobjnum : not used
--- obj : used
--- immediateobj : used
--- objtype : not used
--- pageref : used
--- print : can be used
--- refobj : used
--- registerannot : not to be used
--- reserveobj : used
-
--- pdf.catalog : used
--- pdf.info : used
--- pdf.trailer : used
--- pdf.names : not to be used
-
--- pdf.setinfo : used
--- pdf.setcatalog : used
--- pdf.setnames : not to be used
--- pdf.settrailer : used
-
--- pdf.getinfo : used
--- pdf.getcatalog : used
--- pdf.getnames : not to be used
--- pdf.gettrailer : used
-
-local pdf = pdf
-local factor = number.dimenfactors.bp
-
-if pdf.setinfo then
- -- table.setmetatablenewindex(pdf,function(t,k,v)
- -- report_blocked("'pdf.%s' is not supported",k)
- -- end)
- -- the getters are harmless
-end
-
-do
-
- local texget = tex.get
- local texset = tex.set
-
- if pdf.setminorversion then
- function pdf.setmajorversion (n) texset("global","pdfmajorversion", n) end
- function pdf.getmajorversion ( ) return texget("pdfmajorversion") end
- else
- --
- function pdf.setmajorversion (n) texset("global","pdfmajorversion",n) end
- function pdf.setminorversion (n) texset("global","pdfminorversion",n) end
- function pdf.setcompresslevel (n) texset("global","pdfcompresslevel",n) end
- function pdf.setobjcompresslevel(n) texset("global","pdfobjcompresslevel",n) end
- --
- function pdf.getmajorversion ( ) return texget("pdfmajorversion") end
- function pdf.getminorversion ( ) return texget("pdfminorversion") end
- function pdf.getcompresslevel ( ) return texget("pdfcompresslevel") end
- function pdf.getobjcompresslevel( ) return texget("pdfobjcompresslevel") end
- end
-
-end
-
-if not pdf.setinfo then
- function pdf.setinfo (s) pdf.info = s end
- function pdf.setcatalog(s) pdf.catalog = s end
- function pdf.setnames (s) pdf.names = s end
- function pdf.settrailer(s) pdf.trailer = s end
-end
-
-if not pdf.getpos then
- function pdf.getpos () return pdf.h, pdf.v end
- function pdf.gethpos () return pdf.h end
- function pdf.getvpos () return pdf.v end
- function pdf.hasmatrix() return false end
- function pdf.getmatrix() return 1, 0, 0, 1, 0, 0 end
-end
-
-if not pdf.setpageresources then
- function pdf.setpageresources (s) pdf.pageresources = s end
- function pdf.setpageattributes (s) pdf.pageattributes = s end
- function pdf.setpagesattributes(s) pdf.pagesattributes = s end
-end
-
-local pdfsetinfo = pdf.setinfo
-local pdfsetcatalog = pdf.setcatalog
-local pdfsetnames = pdf.setnames
-local pdfsettrailer = pdf.settrailer
-
-local pdfsetpageresources = pdf.setpageresources
-local pdfsetpageattributes = pdf.setpageattributes
-local pdfsetpagesattributes = pdf.setpagesattributes
-
-local pdfgetpos = pdf.getpos
-local pdfgethpos = pdf.gethpos
-local pdfgetvpos = pdf.getvpos
-local pdfgetmatrix = pdf.getmatrix
-local pdfhasmatrix = pdf.hasmatrix
-
-local pdfreserveobject = pdf.reserveobj
-local pdfimmediateobject = pdf.immediateobj
-local pdfdeferredobject = pdf.obj
-local pdfreferenceobject = pdf.refobj
-
--- function pdf.setinfo () report_blocked("'pdf.%s' is not supported","setinfo") end -- use lpdf.addtoinfo etc
--- function pdf.setcatalog () report_blocked("'pdf.%s' is not supported","setcatalog") end
--- function pdf.setnames () report_blocked("'pdf.%s' is not supported","setnames") end
--- function pdf.settrailer () report_blocked("'pdf.%s' is not supported","settrailer") end
--- function pdf.setpageresources () report_blocked("'pdf.%s' is not supported","setpageresources") end
--- function pdf.setpageattributes () report_blocked("'pdf.%s' is not supported","setpageattributes") end
--- function pdf.setpagesattributes() report_blocked("'pdf.%s' is not supported","setpagesattributes") end
--- function pdf.registerannot () report_blocked("'pdf.%s' is not supported","registerannot") end
-
-local function pdfdisablecommand(command)
- pdf[command] = function() report_blocked("'pdf.%s' is not supported",command) end
-end
-
-pdfdisablecommand("setinfo")
-pdfdisablecommand("setcatalog")
-pdfdisablecommand("setnames")
-pdfdisablecommand("settrailer")
-pdfdisablecommand("setpageresources")
-pdfdisablecommand("setpageattributes")
-pdfdisablecommand("setpagesattributes")
-pdfdisablecommand("registerannot")
-
-local trace_finalizers = false trackers.register("backend.finalizers", function(v) trace_finalizers = v end)
-local trace_resources = false trackers.register("backend.resources", function(v) trace_resources = v end)
-local trace_objects = false trackers.register("backend.objects", function(v) trace_objects = v end)
-local trace_detail = false trackers.register("backend.detail", function(v) trace_detail = v end)
-
-local backends = backends
-local pdfbackend = {
- comment = "backend for directly generating pdf output",
- nodeinjections = { },
- codeinjections = { },
- registrations = { },
- tables = { },
-}
-backends.pdf = pdfbackend
-lpdf = lpdf or { }
-local lpdf = lpdf
-
-local codeinjections = pdfbackend.codeinjections
-local nodeinjections = pdfbackend.nodeinjections
-
-codeinjections.getpos = pdfgetpos lpdf.getpos = pdfgetpos
-codeinjections.gethpos = pdfgethpos lpdf.gethpos = pdfgethpos
-codeinjections.getvpos = pdfgetvpos lpdf.getvpos = pdfgetvpos
-codeinjections.hasmatrix = pdfhasmatrix lpdf.hasmatrix = pdfhasmatrix
-codeinjections.getmatrix = pdfgetmatrix lpdf.getmatrix = pdfgetmatrix
-
--- local function transform(llx,lly,urx,ury,rx,sx,sy,ry)
--- local x1 = llx * rx + lly * sy
--- local y1 = llx * sx + lly * ry
--- local x2 = llx * rx + ury * sy
--- local y2 = llx * sx + ury * ry
--- local x3 = urx * rx + lly * sy
--- local y3 = urx * sx + lly * ry
--- local x4 = urx * rx + ury * sy
--- local y4 = urx * sx + ury * ry
--- llx = min(x1,x2,x3,x4);
--- lly = min(y1,y2,y3,y4);
--- urx = max(x1,x2,x3,x4);
--- ury = max(y1,y2,y3,y4);
--- return llx, lly, urx, ury
--- end
-
-function lpdf.transform(llx,lly,urx,ury) -- not yet used so unchecked
- if pdfhasmatrix() then
- local sx, rx, ry, sy = pdfgetmatrix()
- local w, h = urx - llx, ury - lly
- return llx, lly, llx + sy*w - ry*h, lly + sx*h - rx*w
- -- return transform(llx,lly,urx,ury,sx,rx,ry,sy)
- else
- return llx, lly, urx, ury
- end
-end
-
--- funny values for tx and ty
-
-function lpdf.rectangle(width,height,depth)
- local tx, ty = pdfgetpos()
- if pdfhasmatrix() then
- local rx, sx, sy, ry = pdfgetmatrix()
- return
- factor * tx,
- factor * (ty - ry*depth + sx*width),
- factor * (tx + rx*width - sy*height),
- factor * (ty + ry*height - sx*width)
- else
- return
- factor * tx,
- factor * (ty - depth),
- factor * (tx + width),
- factor * (ty + height)
- end
-end
-
--- we could use a hash of predefined unicodes
-
--- local function tosixteen(str) -- an lpeg might be faster (no table)
--- if not str or str == "" then
--- return "<feff>" -- not () as we want an indication that it's unicode
--- else
--- local r, n = { "<feff" }, 1
--- for b in utfvalues(str) do
--- n = n + 1
--- if b < 0x10000 then
--- r[n] = format("%04x",b)
--- else
--- -- r[n] = format("%04x%04x",b/1024+0xD800,b%1024+0xDC00)
--- r[n] = format("%04x%04x",floor(b/1024),b%1024+0xDC00) --bit32.rshift(b,10)
--- end
--- end
--- n = n + 1
--- r[n] = ">"
--- return concat(r)
--- end
--- end
-
-local cache = table.setmetatableindex(function(t,k) -- can be made weak
- local v = utfbyte(k)
- if v < 0x10000 then
- v = format("%04x",v)
- else
- -- v = format("%04x%04x",v/1024+0xD800,v%1024+0xDC00)
- v = format("%04x%04x",floor(v/1024),v%1024+0xDC00)
- end
- t[k] = v
- return v
-end)
-
-local escaped = Cs(Cc("(") * (S("\\()")/"\\%0" + P(1))^0 * Cc(")"))
-local unified = Cs(Cc("<feff") * (lpeg.patterns.utf8character/cache)^1 * Cc(">"))
-
-local function tosixteen(str) -- an lpeg might be faster (no table)
- if not str or str == "" then
- return "<feff>" -- not () as we want an indication that it's unicode
- else
- return lpegmatch(unified,str)
- end
-end
-
-local more = 0
-
-local pattern = C(4) / function(s) -- needs checking !
- local now = tonumber(s,16)
- if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
- more = 0
- return utfchar(now)
- elseif now >= 0xD800 and now <= 0xDBFF then
- more = now
- return "" -- else the c's end up in the stream
- else
- return utfchar(now)
- end
-end
-
-local pattern = P(true) / function() more = 0 end * Cs(pattern^0)
-
-local function fromsixteen(str)
- if not str or str == "" then
- return ""
- else
- return lpegmatch(pattern,str)
- end
-end
-
-local toregime = regimes.toregime
-local fromregime = regimes.fromregime
-
-local function topdfdoc(str,default)
- if not str or str == "" then
- return ""
- else
- return lpegmatch(escaped,toregime("pdfdoc",str,default)) -- could be combined if needed
- end
-end
-
-local function frompdfdoc(str)
- if not str or str == "" then
- return ""
- else
- return fromregime("pdfdoc",str)
- end
-end
-
-if not toregime then topdfdoc = function(s) return s end end
-if not fromregime then frompdfdoc = function(s) return s end end
-
-local function toeight(str)
- if not str or str == "" then
- return "()"
- else
- return lpegmatch(escaped,str)
- end
-end
-
-lpdf.tosixteen = tosixteen
-lpdf.toeight = toeight
-lpdf.topdfdoc = topdfdoc
-lpdf.fromsixteen = fromsixteen
-lpdf.frompdfdoc = frompdfdoc
-
-local function merge_t(a,b)
- local t = { }
- for k,v in next, a do t[k] = v end
- for k,v in next, b do t[k] = v end
- return setmetatable(t,getmetatable(a))
-end
-
-local f_key_null = formatters["/%s null"]
-local f_key_value = formatters["/%s %s"]
-local f_key_dictionary = formatters["/%s << % t >>"]
-local f_dictionary = formatters["<< % t >>"]
-local f_key_array = formatters["/%s [ % t ]"]
-local f_array = formatters["[ % t ]"]
-local f_key_number = formatters["/%s %F"]
-local f_tonumber = formatters["%F"]
-
--- local f_key_value = formatters["/%s %s"]
--- local f_key_dictionary = formatters["/%s <<% t>>"]
--- local f_dictionary = formatters["<<% t>>"]
--- local f_key_array = formatters["/%s [% t]"]
--- local f_array = formatters["[% t]"]
-
-local tostring_a, tostring_d
-
-tostring_d = function(t,contentonly,key)
- if next(t) then
- local r, rn = { }, 0
- for k, v in next, t do
- rn = rn + 1
- local tv = type(v)
- if tv == "string" then
- r[rn] = f_key_value(k,toeight(v))
- elseif tv == "number" then
- r[rn] = f_key_number(k,v)
- -- elseif tv == "unicode" then -- can't happen
- -- r[rn] = f_key_value(k,tosixteen(v))
- elseif tv == "table" then
- local mv = getmetatable(v)
- if mv and mv.__lpdftype then
- -- if v == t then
- -- report_objects("ignoring circular reference in dirctionary")
- -- r[rn] = f_key_null(k)
- -- else
- r[rn] = f_key_value(k,tostring(v))
- -- end
- elseif v[1] then
- r[rn] = f_key_value(k,tostring_a(v))
- else
- r[rn] = f_key_value(k,tostring_d(v))
- end
- else
- r[rn] = f_key_value(k,tostring(v))
- end
- end
- if contentonly then
- return concat(r," ")
- elseif key then
- return f_key_dictionary(key,r)
- else
- return f_dictionary(r)
- end
- elseif contentonly then
- return ""
- else
- return "<< >>"
- end
-end
-
-tostring_a = function(t,contentonly,key)
- local tn = #t
- if tn ~= 0 then
- local r = { }
- for k=1,tn do
- local v = t[k]
- local tv = type(v)
- if tv == "string" then
- r[k] = toeight(v)
- elseif tv == "number" then
- r[k] = f_tonumber(v)
- -- elseif tv == "unicode" then
- -- r[k] = tosixteen(v)
- elseif tv == "table" then
- local mv = getmetatable(v)
- local mt = mv and mv.__lpdftype
- if mt then
- -- if v == t then
- -- report_objects("ignoring circular reference in array")
- -- r[k] = "null"
- -- else
- r[k] = tostring(v)
- -- end
- elseif v[1] then
- r[k] = tostring_a(v)
- else
- r[k] = tostring_d(v)
- end
- else
- r[k] = tostring(v)
- end
- end
- if contentonly then
- return concat(r, " ")
- elseif key then
- return f_key_array(key,r)
- else
- return f_array(r)
- end
- elseif contentonly then
- return ""
- else
- return "[ ]"
- end
-end
-
-local tostring_x = function(t) return concat(t," ") end
-local tostring_s = function(t) return toeight(t[1]) end
-local tostring_p = function(t) return topdfdoc(t[1],t[2]) end
-local tostring_u = function(t) return tosixteen(t[1]) end
------ tostring_n = function(t) return tostring(t[1]) end -- tostring not needed
-local tostring_n = function(t) return f_tonumber(t[1]) end -- tostring not needed
-local tostring_c = function(t) return t[1] end -- already prefixed (hashed)
-local tostring_z = function() return "null" end
-local tostring_t = function() return "true" end
-local tostring_f = function() return "false" end
-local tostring_r = function(t) local n = t[1] return n and n > 0 and (n .. " 0 R") or "null" end
-
-local tostring_v = function(t)
- local s = t[1]
- if type(s) == "table" then
- return concat(s)
- else
- return s
- end
-end
-
-local function value_x(t) return t end
-local function value_s(t) return t[1] end
-local function value_p(t) return t[1] end
-local function value_u(t) return t[1] end
-local function value_n(t) return t[1] end
-local function value_c(t) return sub(t[1],2) end
-local function value_d(t) return tostring_d(t,true) end
-local function value_a(t) return tostring_a(t,true) end
-local function value_z() return nil end
-local function value_t(t) return t.value or true end
-local function value_f(t) return t.value or false end
-local function value_r() return t[1] or 0 end -- null
-local function value_v() return t[1] end
-
-local function add_x(t,k,v) rawset(t,k,tostring(v)) end
-
-local mt_x = { __lpdftype = "stream", __tostring = tostring_x, __call = value_x, __newindex = add_x }
-local mt_d = { __lpdftype = "dictionary", __tostring = tostring_d, __call = value_d }
-local mt_a = { __lpdftype = "array", __tostring = tostring_a, __call = value_a }
-local mt_u = { __lpdftype = "unicode", __tostring = tostring_u, __call = value_u }
-local mt_s = { __lpdftype = "string", __tostring = tostring_s, __call = value_s }
-local mt_p = { __lpdftype = "docstring", __tostring = tostring_p, __call = value_p }
-local mt_n = { __lpdftype = "number", __tostring = tostring_n, __call = value_n }
-local mt_c = { __lpdftype = "constant", __tostring = tostring_c, __call = value_c }
-local mt_z = { __lpdftype = "null", __tostring = tostring_z, __call = value_z }
-local mt_t = { __lpdftype = "true", __tostring = tostring_t, __call = value_t }
-local mt_f = { __lpdftype = "false", __tostring = tostring_f, __call = value_f }
-local mt_r = { __lpdftype = "reference", __tostring = tostring_r, __call = value_r }
-local mt_v = { __lpdftype = "verbose", __tostring = tostring_v, __call = value_v }
-
-local function pdfstream(t) -- we need to add attributes
- if t then
- for i=1,#t do
- t[i] = tostring(t[i])
- end
- end
- return setmetatable(t or { },mt_x)
-end
-
-local function pdfdictionary(t)
- return setmetatable(t or { },mt_d)
-end
-
-local function pdfarray(t)
- if type(t) == "string" then
- return setmetatable({ t },mt_a)
- else
- return setmetatable(t or { },mt_a)
- end
-end
-
-local function pdfstring(str,default)
- return setmetatable({ str or default or "" },mt_s)
-end
-
-local function pdfdocstring(str,default,defaultchar)
- return setmetatable({ str or default or "", defaultchar or " " },mt_p)
-end
-
-local function pdfunicode(str,default)
- return setmetatable({ str or default or "" },mt_u) -- could be a string
-end
-
-local cache = { } -- can be weak
-
-local function pdfnumber(n,default) -- 0-10
- n = n or default
- local c = cache[n]
- if not c then
- c = setmetatable({ n },mt_n)
- -- cache[n] = c -- too many numbers
- end
- return c
-end
-
-for i=-1,9 do cache[i] = pdfnumber(i) end
-
-local cache = { } -- can be weak
-
-local forbidden, replacements = "\0\t\n\r\f ()[]{}/%%#\\", { } -- table faster than function
-
-for s in gmatch(forbidden,".") do
- replacements[s] = format("#%02x",byte(s))
-end
-
-local escaped = Cs(Cc("/") * (S(forbidden)/replacements + P(1))^0)
-
-local function pdfconstant(str,default)
- str = str or default or ""
- local c = cache[str]
- if not c then
- -- c = setmetatable({ "/" .. str },mt_c)
- c = setmetatable({ lpegmatch(escaped,str) },mt_c)
- cache[str] = c
- end
- return c
-end
-
-local escaped = Cs((S(forbidden)/replacements + P(1))^0)
------ escaped = Cs((1-forbidden)^0 * S(forbidden)/replacements * ((S(forbidden)/replacements + P(1))^0)
-
-function lpdf.escaped(str)
- return lpegmatch(escaped,str) or str
-end
-
-local p_null = { } setmetatable(p_null, mt_z)
-local p_true = { } setmetatable(p_true, mt_t)
-local p_false = { } setmetatable(p_false,mt_f)
-
-local function pdfnull()
- return p_null
-end
-
---~ print(pdfboolean(false),pdfboolean(false,false),pdfboolean(false,true))
---~ print(pdfboolean(true),pdfboolean(true,false),pdfboolean(true,true))
---~ print(pdfboolean(nil,true),pdfboolean(nil,false))
-
-local function pdfboolean(b,default)
- if type(b) == "boolean" then
- return b and p_true or p_false
- else
- return default and p_true or p_false
- end
-end
-
-local r_zero = setmetatable({ 0 },mt_r)
-
-local function pdfreference(r) -- maybe make a weak table
- if r and r ~= 0 then
- return setmetatable({ r },mt_r)
- else
- return r_zero
- end
-end
-
-local v_zero = setmetatable({ 0 },mt_v)
-local v_empty = setmetatable({ "" },mt_v)
-
-local function pdfverbose(t) -- maybe check for type
- if t == 0 then
- return v_zero
- elseif t == "" then
- return v_empty
- else
- return setmetatable({ t },mt_v)
- end
-end
-
-lpdf.stream = pdfstream -- THIS WILL PROBABLY CHANGE
-lpdf.dictionary = pdfdictionary
-lpdf.array = pdfarray
-lpdf.docstring = pdfdocstring
-lpdf.string = pdfstring
-lpdf.unicode = pdfunicode
-lpdf.number = pdfnumber
-lpdf.constant = pdfconstant
-lpdf.null = pdfnull
-lpdf.boolean = pdfboolean
-lpdf.reference = pdfreference
-lpdf.verbose = pdfverbose
-
-local names, cache = { }, { }
-
-function lpdf.reserveobject(name)
- local r = pdfreserveobject() -- we don't support "annot"
- if name then
- names[name] = r
- if trace_objects then
- report_objects("reserving number %a under name %a",r,name)
- end
- elseif trace_objects then
- report_objects("reserving number %a",r)
- end
- return r
-end
-
--- lpdf.immediateobject = pdfimmediateobject
--- lpdf.deferredobject = pdfdeferredobject
--- lpdf.object = pdfdeferredobject
--- lpdf.referenceobject = pdfreferenceobject
-
-local pagereference = pdf.pageref -- tex.pdfpageref is obsolete
-local nofpages = 0
-
-function lpdf.pagereference(n)
- if nofpages == 0 then
- nofpages = structures.pages.nofpages
- if nofpages == 0 then
- nofpages = 1
- end
- end
- if n > nofpages then
- return pagereference(nofpages) -- or 1, could be configureable
- else
- return pagereference(n)
- end
-end
-
-function lpdf.delayedobject(data,n)
- if n then
- pdfdeferredobject(n,data)
- else
- n = pdfdeferredobject(data)
- end
- pdfreferenceobject(n)
- return n
-end
-
-function lpdf.flushobject(name,data)
- if data then
- local named = names[name]
- if named then
- if not trace_objects then
- elseif trace_detail then
- report_objects("flushing data to reserved object with name %a, data: %S",name,data)
- else
- report_objects("flushing data to reserved object with name %a",name)
- end
- return pdfimmediateobject(named,tostring(data))
- else
- if not trace_objects then
- elseif trace_detail then
- report_objects("flushing data to reserved object with number %s, data: %S",name,data)
- else
- report_objects("flushing data to reserved object with number %s",name)
- end
- return pdfimmediateobject(name,tostring(data))
- end
- else
- if trace_objects and trace_detail then
- report_objects("flushing data: %S",name)
- end
- return pdfimmediateobject(tostring(name))
- end
-end
-
-
-function lpdf.flushstreamobject(data,dict,compressed) -- default compressed
- if trace_objects then
- report_objects("flushing stream object of %s bytes",#data)
- end
- local dtype = type(dict)
- return pdfdeferredobject {
- immediate = true,
- compresslevel = compressed == false and 0 or nil,
- type = "stream",
- string = data,
- attr = (dtype == "string" and dict) or (dtype == "table" and dict()) or nil,
- }
-end
-
-function lpdf.flushstreamfileobject(filename,dict,compressed) -- default compressed
- if trace_objects then
- report_objects("flushing stream file object %a",filename)
- end
- local dtype = type(dict)
- return pdfdeferredobject {
- immediate = true,
- compresslevel = compressed == false and 0 or nil,
- type = "stream",
- file = filename,
- attr = (dtype == "string" and dict) or (dtype == "table" and dict()) or nil,
- }
-end
-
-local shareobjectcache, shareobjectreferencecache = { }, { }
-
-function lpdf.shareobject(content)
- if content == nil then
- -- invalid object not created
- else
- content = tostring(content)
- local o = shareobjectcache[content]
- if not o then
- o = pdfimmediateobject(content)
- shareobjectcache[content] = o
- end
- return o
- end
-end
-
-function lpdf.shareobjectreference(content)
- if content == nil then
- -- invalid object not created
- else
- content = tostring(content)
- local r = shareobjectreferencecache[content]
- if not r then
- local o = shareobjectcache[content]
- if not o then
- o = pdfimmediateobject(content)
- shareobjectcache[content] = o
- end
- r = pdfreference(o)
- shareobjectreferencecache[content] = r
- end
- return r
- end
-end
-
--- three priority levels, default=2
-
-local pagefinalizers = { { }, { }, { } }
-local documentfinalizers = { { }, { }, { } }
-
-local pageresources, pageattributes, pagesattributes
-
-local function resetpageproperties()
- pageresources = pdfdictionary()
- pageattributes = pdfdictionary()
- pagesattributes = pdfdictionary()
-end
-
-resetpageproperties()
-
-local function setpageproperties()
- pdfsetpageresources (pageresources ())
- pdfsetpageattributes (pageattributes ())
- pdfsetpagesattributes(pagesattributes())
-end
-
-local function addtopageresources (k,v) pageresources [k] = v end
-local function addtopageattributes (k,v) pageattributes [k] = v end
-local function addtopagesattributes(k,v) pagesattributes[k] = v end
-
-lpdf.addtopageresources = addtopageresources
-lpdf.addtopageattributes = addtopageattributes
-lpdf.addtopagesattributes = addtopagesattributes
-
-local function set(where,what,f,when,comment)
- if type(when) == "string" then
- when, comment = 2, when
- elseif not when then
- when = 2
- end
- local w = where[when]
- w[#w+1] = { f, comment }
- if trace_finalizers then
- report_finalizing("%s set: [%s,%s]",what,when,#w)
- end
-end
-
-local function run(where,what)
- if trace_finalizers then
- report_finalizing("start backend, category %a, n %a",what,#where)
- end
- for i=1,#where do
- local w = where[i]
- for j=1,#w do
- local wj = w[j]
- if trace_finalizers then
- report_finalizing("%s finalizer: [%s,%s] %s",what,i,j,wj[2] or "")
- end
- wj[1]()
- end
- end
- if trace_finalizers then
- report_finalizing("stop finalizing")
- end
-end
-
-local function registerpagefinalizer(f,when,comment)
- set(pagefinalizers,"page",f,when,comment)
-end
-
-local function registerdocumentfinalizer(f,when,comment)
- set(documentfinalizers,"document",f,when,comment)
-end
-
-lpdf.registerpagefinalizer = registerpagefinalizer
-lpdf.registerdocumentfinalizer = registerdocumentfinalizer
-
-function lpdf.finalizepage(shipout)
- if shipout and not environment.initex then
- -- resetpageproperties() -- maybe better before
- run(pagefinalizers,"page")
- setpageproperties()
- resetpageproperties() -- maybe better before
- end
-end
-
-function lpdf.finalizedocument()
- if not environment.initex then
- run(documentfinalizers,"document")
- function lpdf.finalizedocument()
- report_finalizing("serious error: the document is finalized multiple times")
- function lpdf.finalizedocument() end
- end
- end
-end
-
--- codeinjections.finalizepage = lpdf.finalizepage -- no longer triggered at the tex end
-
-if not callbacks.register("finish_pdfpage", lpdf.finalizepage) then
-
- local find_tail = nodes.tail
- local latelua_node = nodes.pool.latelua
-
- function nodeinjections.finalizepage(head)
- local t = find_tail(head.list)
- if t then
- local n = latelua_node("lpdf.finalizepage(true)") -- last in the shipout
- t.next = n
- n.prev = t
- end
- return head, true
- end
-
- nodes.tasks.appendaction("shipouts","normalizers","backends.pdf.nodeinjections.finalizepage")
-
-end
-
-callbacks.register("finish_pdffile", lpdf.finalizedocument)
-
-
-do
-
- -- some minimal tracing, handy for checking the order
-
- local function trace_set(what,key)
- if trace_resources then
- report_finalizing("setting key %a in %a",key,what)
- end
- end
-
- local function trace_flush(what)
- if trace_resources then
- report_finalizing("flushing %a",what)
- end
- end
-
- lpdf.protectresources = true
-
- local catalog = pdfdictionary { Type = pdfconstant("Catalog") } -- nicer, but when we assign we nil the Type
- local info = pdfdictionary { Type = pdfconstant("Info") } -- nicer, but when we assign we nil the Type
- ----- names = pdfdictionary { Type = pdfconstant("Names") } -- nicer, but when we assign we nil the Type
-
- local function flushcatalog()
- if not environment.initex then
- trace_flush("catalog")
- catalog.Type = nil
- pdfsetcatalog(catalog())
- end
- end
-
- local function flushinfo()
- if not environment.initex then
- trace_flush("info")
- info.Type = nil
- pdfsetinfo(info())
- end
- end
-
- -- local function flushnames()
- -- if not environment.initex then
- -- trace_flush("names")
- -- names.Type = nil
- -- pdfsetnames(names())
- -- end
- -- end
-
- function lpdf.addtocatalog(k,v)
- if not (lpdf.protectresources and catalog[k]) then
- trace_set("catalog",k)
- catalog[k] = v
- end
- end
-
- function lpdf.addtoinfo(k,v)
- if not (lpdf.protectresources and info[k]) then
- trace_set("info",k)
- info[k] = v
- end
- end
-
- -- local function lpdf.addtonames(k,v)
- -- if not (lpdf.protectresources and names[k]) then
- -- trace_set("names",k)
- -- names[k] = v
- -- end
- -- end
-
- local names = pdfdictionary {
- -- Type = pdfconstant("Names")
- }
-
- local function flushnames()
- if next(names) and not environment.initex then
- names.Type = pdfconstant("Names")
- trace_flush("names")
- lpdf.addtocatalog("Names",pdfreference(pdfimmediateobject(tostring(names))))
- end
- end
-
- function lpdf.addtonames(k,v)
- if not (lpdf.protectresources and names[k]) then
- trace_set("names", k)
- names [k] = v
- end
- end
-
- local r_extgstates, d_extgstates = pdfreserveobject(), pdfdictionary() local p_extgstates = pdfreference(r_extgstates)
- local r_colorspaces, d_colorspaces = pdfreserveobject(), pdfdictionary() local p_colorspaces = pdfreference(r_colorspaces)
- local r_patterns, d_patterns = pdfreserveobject(), pdfdictionary() local p_patterns = pdfreference(r_patterns)
- local r_shades, d_shades = pdfreserveobject(), pdfdictionary() local p_shades = pdfreference(r_shades)
-
- local function checkextgstates () if next(d_extgstates ) then addtopageresources("ExtGState", p_extgstates ) end end
- local function checkcolorspaces() if next(d_colorspaces) then addtopageresources("ColorSpace",p_colorspaces) end end
- local function checkpatterns () if next(d_patterns ) then addtopageresources("Pattern", p_patterns ) end end
- local function checkshades () if next(d_shades ) then addtopageresources("Shading", p_shades ) end end
-
- local function flushextgstates () if next(d_extgstates ) then trace_flush("extgstates") pdfimmediateobject(r_extgstates, tostring(d_extgstates )) end end
- local function flushcolorspaces() if next(d_colorspaces) then trace_flush("colorspaces") pdfimmediateobject(r_colorspaces,tostring(d_colorspaces)) end end
- local function flushpatterns () if next(d_patterns ) then trace_flush("patterns") pdfimmediateobject(r_patterns, tostring(d_patterns )) end end
- local function flushshades () if next(d_shades ) then trace_flush("shades") pdfimmediateobject(r_shades, tostring(d_shades )) end end
-
- function lpdf.collectedresources()
- local ExtGState = next(d_extgstates ) and p_extgstates
- local ColorSpace = next(d_colorspaces) and p_colorspaces
- local Pattern = next(d_patterns ) and p_patterns
- local Shading = next(d_shades ) and p_shades
- if ExtGState or ColorSpace or Pattern or Shading then
- local collected = pdfdictionary {
- ExtGState = ExtGState,
- ColorSpace = ColorSpace,
- Pattern = Pattern,
- Shading = Shading,
- -- ProcSet = pdfarray { pdfconstant("PDF") },
- }
- return collected()
- else
- return ""
- end
- end
-
- function lpdf.adddocumentextgstate (k,v) d_extgstates [k] = v end
- function lpdf.adddocumentcolorspace(k,v) d_colorspaces[k] = v end
- function lpdf.adddocumentpattern (k,v) d_patterns [k] = v end
- function lpdf.adddocumentshade (k,v) d_shades [k] = v end
-
- registerdocumentfinalizer(flushextgstates,3,"extended graphic states")
- registerdocumentfinalizer(flushcolorspaces,3,"color spaces")
- registerdocumentfinalizer(flushpatterns,3,"patterns")
- registerdocumentfinalizer(flushshades,3,"shades")
-
- registerdocumentfinalizer(flushnames,3,"names") -- before catalog
- registerdocumentfinalizer(flushcatalog,3,"catalog")
- registerdocumentfinalizer(flushinfo,3,"info")
-
- registerpagefinalizer(checkextgstates,3,"extended graphic states")
- registerpagefinalizer(checkcolorspaces,3,"color spaces")
- registerpagefinalizer(checkpatterns,3,"patterns")
- registerpagefinalizer(checkshades,3,"shades")
-
-end
-
--- in strc-bkm: lpdf.registerdocumentfinalizer(function() structures.bookmarks.place() end,1)
-
-function lpdf.rotationcm(a)
- local s, c = sind(a), cosd(a)
- return format("%0.6F %0.6F %0.6F %0.6F 0 0 cm",c,s,-s,c)
-end
-
--- ! -> universaltime
-
-do
-
- local timestamp = os.date("%Y-%m-%dT%X") .. os.timezone(true)
-
- function lpdf.timestamp()
- return timestamp
- end
-
- function lpdf.pdftimestamp(str)
- 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)
- end
-
- function lpdf.id()
- return format("%s.%s",tex.jobname,timestamp)
- end
-
-end
-
--- return nil is nicer in test prints
-
-function lpdf.checkedkey(t,key,variant)
- local pn = t and t[key]
- if pn ~= nil then
- local tn = type(pn)
- if tn == variant then
- if variant == "string" then
- if pn ~= "" then
- return pn
- end
- elseif variant == "table" then
- if next(pn) then
- return pn
- end
- else
- return pn
- end
- elseif tn == "string" then
- if variant == "number" then
- return tonumber(pn)
- elseif variant == "boolean" then
- return isboolean(pn,nil,true)
- end
- end
- end
- -- return nil
-end
-
-function lpdf.checkedvalue(value,variant) -- code not shared
- if value ~= nil then
- local tv = type(value)
- if tv == variant then
- if variant == "string" then
- if value ~= "" then
- return value
- end
- elseif variant == "table" then
- if next(value) then
- return value
- end
- else
- return value
- end
- elseif tv == "string" then
- if variant == "number" then
- return tonumber(value)
- elseif variant == "boolean" then
- return isboolean(value,nil,true)
- end
- end
- end
- -- return nil
-end
-
-function lpdf.limited(n,min,max,default)
- if not n then
- return default
- else
- n = tonumber(n)
- if not n then
- return default
- elseif n > max then
- return max
- elseif n < min then
- return min
- else
- return n
- end
- end
-end
-
--- lpdf.addtoinfo("ConTeXt.Version", environment.version)
--- lpdf.addtoinfo("ConTeXt.Time", os.date("%Y.%m.%d %H:%M")) -- :%S
--- lpdf.addtoinfo("ConTeXt.Jobname", environment.jobname)
--- lpdf.addtoinfo("ConTeXt.Url", "www.pragma-ade.com")
--- lpdf.addtoinfo("ConTeXt.Support", "contextgarden.net")
-
--- if not pdfreferenceobject then
---
--- local delayed = { }
---
--- local function flush()
--- local n = 0
--- for k,v in next, delayed do
--- pdfimmediateobject(k,v)
--- n = n + 1
--- end
--- if trace_objects then
--- report_objects("%s objects flushed",n)
--- end
--- delayed = { }
--- end
---
--- lpdf.registerdocumentfinalizer(flush,3,"objects") -- so we need a final flush too
--- lpdf.registerpagefinalizer (flush,3,"objects") -- somehow this lags behind .. I need to look into that some day
---
--- function lpdf.delayedobject(data)
--- local n = pdfreserveobject()
--- delayed[n] = data
--- return n
--- end
---
--- end
-
--- setmetatable(pdf, {
--- __index = function(t,k)
--- if k == "info" then return pdf.getinfo()
--- elseif k == "catalog" then return pdf.getcatalog()
--- elseif k == "names" then return pdf.getnames()
--- elseif k == "trailer" then return pdf.gettrailer()
--- elseif k == "pageattribute" then return pdf.getpageattribute()
--- elseif k == "pageattributes" then return pdf.getpageattributes()
--- elseif k == "pageresources" then return pdf.getpageresources()
--- elseif
--- return nil
--- end
--- end,
--- __newindex = function(t,k,v)
--- if k == "info" then return pdf.setinfo(v)
--- elseif k == "catalog" then return pdf.setcatalog(v)
--- elseif k == "names" then return pdf.setnames(v)
--- elseif k == "trailer" then return pdf.settrailer(v)
--- elseif k == "pageattribute" then return pdf.setpageattribute(v)
--- elseif k == "pageattributes" then return pdf.setpageattributes(v)
--- elseif k == "pageresources" then return pdf.setpageresources(v)
--- else
--- rawset(t,k,v)
--- end
--- end,
--- })
-
-
--- The next variant of ActualText is what Taco and I could come up with
--- eventually. As of September 2013 Acrobat copies okay, Sumatra copies a
--- question mark, pdftotext injects an extra space and Okular adds a
--- newline plus space.
-
--- return formatters["BT /Span << /ActualText (CONTEXT) >> BDC [<feff>] TJ % t EMC ET"](code)
-
-do
-
- local f_actual_text_one = formatters["BT /Span << /ActualText <feff%04x> >> BDC [<feff>] TJ %s EMC ET"]
- local f_actual_text_two = formatters["BT /Span << /ActualText <feff%04x%04x> >> BDC [<feff>] TJ %s EMC ET"]
- local f_actual_text = formatters["/Span <</ActualText %s >> BDC"]
-
- local context = context
- local pdfdirect = nodes.pool.pdfdirect
-
- function codeinjections.unicodetoactualtext(unicode,pdfcode)
- if unicode < 0x10000 then
- return f_actual_text_one(unicode,pdfcode)
- else
- return f_actual_text_two(unicode/1024+0xD800,unicode%1024+0xDC00,pdfcode)
- end
- end
-
- implement {
- name = "startactualtext",
- arguments = "string",
- actions = function(str)
- context(pdfdirect(f_actual_text(tosixteen(str))))
- end
- }
-
- implement {
- name = "stopactualtext",
- actions = function()
- context(pdfdirect("EMC"))
- end
- }
-
-end
-
--- interface
-
-local lpdfverbose = lpdf.verbose
-
-implement { name = "lpdf_collectedresources", actions = { lpdf.collectedresources, context } }
-implement { name = "lpdf_addtocatalog", arguments = two_strings, actions = lpdf.addtocatalog }
-implement { name = "lpdf_addtoinfo", arguments = two_strings, actions = lpdf.addtoinfo }
-implement { name = "lpdf_addtonames", arguments = two_strings, actions = lpdf.addtonames }
-implement { name = "lpdf_addtopageattributes", arguments = two_strings, actions = lpdf.addtopageattributes }
-implement { name = "lpdf_addtopagesattributes", arguments = two_strings, actions = lpdf.addtopagesattributes }
-implement { name = "lpdf_addtopageresources", arguments = two_strings, actions = lpdf.addtopageresources }
-implement { name = "lpdf_adddocumentextgstate", arguments = two_strings, actions = function(a,b) lpdf.adddocumentextgstate (a,lpdfverbose(b)) end }
-implement { name = "lpdf_adddocumentcolorspace", arguments = two_strings, actions = function(a,b) lpdf.adddocumentcolorspace(a,lpdfverbose(b)) end }
-implement { name = "lpdf_adddocumentpattern", arguments = two_strings, actions = function(a,b) lpdf.adddocumentpattern (a,lpdfverbose(b)) end }
-implement { name = "lpdf_adddocumentshade", arguments = two_strings, actions = function(a,b) lpdf.adddocumentshade (a,lpdfverbose(b)) end }
-