diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/lpdf-ini.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/lpdf-ini.lua | 589 |
1 files changed, 399 insertions, 190 deletions
diff --git a/Master/texmf-dist/tex/context/base/lpdf-ini.lua b/Master/texmf-dist/tex/context/base/lpdf-ini.lua index 025f62c4f84..834f845c59a 100644 --- a/Master/texmf-dist/tex/context/base/lpdf-ini.lua +++ b/Master/texmf-dist/tex/context/base/lpdf-ini.lua @@ -6,17 +6,27 @@ if not modules then modules = { } end modules ['lpdf-ini'] = { 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, utfvalues = utf.char, utf.values +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 @@ -56,9 +66,9 @@ 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) + -- table.setmetatablenewindex(pdf,function(t,k,v) + -- report_blocked("'pdf.%s' is not supported",k) + -- end) -- the getters are harmless end @@ -103,15 +113,27 @@ 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.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 -function pdf.registerannot() report_blocked("'pdf.%s' is not supported","registerannot") 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) @@ -180,67 +202,112 @@ function lpdf.rectangle(width,height,depth) 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 - 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) - end - end - n = n + 1 - r[n] = ">" - return concat(r) + return lpegmatch(unified,str) end end -lpdf.tosixteen = tosixteen +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 --- lpeg is some 5 times faster than gsub (in test) on escaping +local pattern = P(true) / function() more = 0 end * Cs(pattern^0) --- local escapes = { --- ["\\"] = "\\\\", --- ["/"] = "\\/", ["#"] = "\\#", --- ["<"] = "\\<", [">"] = "\\>", --- ["["] = "\\[", ["]"] = "\\]", --- ["("] = "\\(", [")"] = "\\)", --- } --- --- local escaped = Cs(Cc("(") * (S("\\/#<>[]()")/escapes + P(1))^0 * Cc(")")) --- --- local function toeight(str) --- if not str or str == "" then --- return "()" --- else --- return lpegmatch(escaped,str) --- end --- end --- --- -- no need for escaping .. just use unicode instead +local function fromsixteen(str) + if not str or str == "" then + return "" + else + return lpegmatch(pattern,str) + end +end --- \0 \t \n \r \f <space> ( ) [ ] { } / % +local toregime = regimes.toregime +local fromregime = regimes.fromregime -local function toeight(str) - return "(" .. str .. ")" +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 -lpdf.toeight = toeight +local function frompdfdoc(str) + if not str or str == "" then + return "" + else + return fromregime("pdfdoc",str) + end +end --- local escaped = lpeg.Cs((lpeg.S("\0\t\n\r\f ()[]{}/%")/function(s) return format("#%02X",byte(s)) end + lpeg.P(1))^0) --- --- local function cleaned(str) --- return (str and str ~= "" and lpegmatch(escaped,str)) or "" --- end --- --- lpdf.cleaned = cleaned -- not public yet +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 = { } @@ -249,6 +316,7 @@ local function merge_t(a,b) 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 >>"] @@ -275,12 +343,17 @@ tostring_d = function(t,contentonly,key) r[rn] = f_key_value(k,toeight(v)) elseif tv == "number" then r[rn] = f_key_number(k,v) - elseif tv == "unicode" then - r[rn] = f_key_value(k,tosixteen(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 - r[rn] = f_key_value(k,tostring(v)) + -- 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 @@ -315,13 +388,18 @@ tostring_a = function(t,contentonly,key) r[k] = toeight(v) elseif tv == "number" then r[k] = f_tonumber(v) - elseif tv == "unicode" then - r[k] = tosixteen(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 - r[k] = tostring(v) + -- 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 @@ -345,16 +423,17 @@ tostring_a = function(t,contentonly,key) end end -local tostring_x = function(t) return concat(t," ") end -local tostring_s = function(t) return toeight(t[1]) end -local tostring_u = function(t) return tosixteen(t[1]) end -local 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_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] @@ -365,18 +444,19 @@ local tostring_v = function(t) end end -local function value_x(t) return t end -- the call is experimental -local function value_s(t,key) return t[1] end -- the call is experimental -local function value_u(t,key) return t[1] end -- the call is experimental -local function value_n(t,key) return t[1] end -- the call is experimental -local function value_c(t) return sub(t[1],2) end -- the call is experimental -local function value_d(t) return tostring_d(t,true) end -- the call is experimental -local function value_a(t) return tostring_a(t,true) end -- the call is experimental -local function value_z() return nil end -- the call is experimental -local function value_t(t) return t.value or true end -- the call is experimental -local function value_f(t) return t.value or false end -- the call is experimental -local function value_r() return t[1] or 0 end -- the call is experimental -- NULL -local function value_v() return t[1] end -- the call is experimental +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 @@ -385,6 +465,7 @@ local mt_d = { __lpdftype = "dictionary", __tostring = tostring_d, __call = valu 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 } @@ -418,8 +499,12 @@ 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) + return setmetatable({ str or default or "" },mt_u) -- could be a string end local cache = { } -- can be weak @@ -503,6 +588,7 @@ 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 @@ -532,7 +618,7 @@ end -- lpdf.object = pdfdeferredobject -- lpdf.referenceobject = pdfreferenceobject -local pagereference = pdf.pageref or tex.pdfpageref +local pagereference = pdf.pageref -- tex.pdfpageref is obsolete local nofpages = 0 function lpdf.pagereference(n) @@ -765,108 +851,147 @@ end callbacks.register("finish_pdffile", lpdf.finalizedocument) --- 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 +do -lpdf.protectresources = true + -- some minimal tracing, handy for checking the order -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 trace_set(what,key) + if trace_resources then + report_finalizing("setting key %a in %a",key,what) + end + end -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 --------------- flushnames () if not environment.initex then trace_flush("names") names .Type = nil pdfsetnames (names ()) end end + local function trace_flush(what) + if trace_resources then + report_finalizing("flushing %a",what) + 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 --------- lpdf.addtonames (k,v) if not (lpdf.protectresources and names [k]) then trace_set("names", k) names [k] = v end end + lpdf.protectresources = true -local names = pdfdictionary { - -- Type = pdfconstant("Names") -} + 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 flushnames() - if next(names) and not environment.initex then - names.Type = pdfconstant("Names") - trace_flush("names") - lpdf.addtocatalog("Names",pdfreference(pdfimmediateobject(tostring(names)))) + local function flushcatalog() + if not environment.initex then + trace_flush("catalog") + catalog.Type = nil + pdfsetcatalog(catalog()) + end end -end -function lpdf.addtonames(k,v) - if not (lpdf.protectresources and names [k]) then - trace_set("names", k) - names [k] = v + local function flushinfo() + if not environment.initex then + trace_flush("info") + info.Type = nil + pdfsetinfo(info()) + end end -end -local dummy = pdfreserveobject() -- else bug in hvmd due so some internal luatex conflict + -- 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 --- Some day I will implement a proper minimalized resource management. + function lpdf.addtoinfo(k,v) + if not (lpdf.protectresources and info[k]) then + trace_set("info",k) + info[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 lpdf.addtonames(k,v) + -- if not (lpdf.protectresources and names[k]) then + -- trace_set("names",k) + -- names[k] = v + -- end + -- end -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 names = pdfdictionary { + -- Type = pdfconstant("Names") + } -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 + 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.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 "" + 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 -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 + 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(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") + 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") + 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) @@ -877,54 +1002,78 @@ end -- ! -> universaltime -local timestamp = os.date("%Y-%m-%dT%X") .. os.timezone(true) +do -function lpdf.timestamp() - return timestamp -end + local timestamp = os.date("%Y-%m-%dT%X") .. os.timezone(true) -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.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 -function lpdf.id() - return format("%s.%s",tex.jobname,timestamp) end +-- return nil is nicer in test prints + function lpdf.checkedkey(t,key,variant) local pn = t and t[key] - if pn then + if pn ~= nil then local tn = type(pn) if tn == variant then if variant == "string" then - return pn ~= "" and pn or nil + if pn ~= "" then + return pn + end elseif variant == "table" then - return next(pn) and pn or nil + if next(pn) then + return pn + end else return pn end - elseif tn == "string" and variant == "number" then - return tonumber(pn) + 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 then + if value ~= nil then local tv = type(value) if tv == variant then if variant == "string" then - return value ~= "" and value + if value ~= "" then + return value + end elseif variant == "table" then - return next(value) and value + if next(value) then + return value + end else return value end - elseif tv == "string" and variant == "number" then - return tonumber(value) + 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) @@ -944,10 +1093,11 @@ function lpdf.limited(n,min,max,default) end end --- lpdf.addtoinfo("ConTeXt.Version", tex.contextversiontoks) +-- 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 -- @@ -1002,3 +1152,62 @@ end -- 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_addpageattributes", arguments = two_strings, actions = lpdf.addtopageattributes } +implement { name = "lpdf_addpagesattributes", arguments = two_strings, actions = lpdf.addtopagesattributes } +implement { name = "lpdf_addpageresources", 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 } + |