summaryrefslogtreecommitdiff
path: root/tex/context/base/attr-ini.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/attr-ini.lua')
-rw-r--r--tex/context/base/attr-ini.lua697
1 files changed, 345 insertions, 352 deletions
diff --git a/tex/context/base/attr-ini.lua b/tex/context/base/attr-ini.lua
index 4469608c4..81ca873d9 100644
--- a/tex/context/base/attr-ini.lua
+++ b/tex/context/base/attr-ini.lua
@@ -29,11 +29,17 @@ function totokens(str)
return t
end
-function pdfliteral(str)
- local t = node.new('whatsit',8)
- t.mode = 1 -- direct
- t.data = str -- totokens(str)
- return t
+-- temp hack, will be proper driver stuff
+
+backends = backends or { }
+backends.pdf = backends.pdf or { }
+backend = backend or backends.pdf
+
+function backends.pdf.literal(str)
+ local t = node.new('whatsit',8)
+ t.mode = 1 -- direct
+ t.data = str -- totokens(str)
+ return t
end
-- shipouts
@@ -45,44 +51,44 @@ do
local hlist, vlist = node.id('hlist'), node.id('vlist')
- local function do_process_page(attribute,processor,head) -- maybe work with ranges
- local previous, stack = nil, head
- while stack do
- local id = stack.id
- if id == hlist or id == vlist then
- local content = stack.list
- if content then
- stack.list = do_process_page(attribute,processor,content)
- end
- else
- stack, previous, head = processor(attribute,stack,previous,head)
- end
- previous = stack
- stack = stack.next
- end
- return head
- end
+ local contains = node.has_attribute
+
+ nodes.trigger = false
+ nodes.triggering = false
+
+ -- we used to do the main processor loop here and call processor for each node
+ -- but eventually this was too much a slow down (1 sec on 23 for 120 pages mk)
+ -- so that we moved looping to teh processor itself; this may lead to a bit of
+ -- duplicate code once that we have more state handlers
function nodes.process_page(head)
+ local trigger = nodes.trigger
if head then
- input.start_timing(nodes)
+ input.start_timing(attributes)
local done, used = false, { }
for name, plugin in pairs(shipouts.plugins) do
local attribute = attributes.numbers[name]
if attribute then
- local initializer = plugin.initializer
- local processor = plugin.processor
- local finalizer = plugin.finalizer
- if initializer then
- initializer(attribute,head)
- end
- if processor then
- head = do_process_page(attribute,processor,head)
- end
- if finalizer then
- local ok
- ok, head, used[attribute] = finalizer(attribute,head)
- done = done or ok
+ local namespace = plugin.namespace
+ if namespace.enabled then
+ local initializer = plugin.initializer
+ local processor = plugin.processor
+ local finalizer = plugin.finalizer
+ local resolver = plugin.resolver
+ if initializer then
+ initializer(namespace,attribute,head)
+ end
+ if processor then
+ local inheritance = (resolver and resolver()) or -1
+ local ok
+ ok, head = processor(namespace,attribute,head,inheritance)
+ done = done or ok
+ end
+ if finalizer then -- no need when not ok
+ local ok
+ ok, head, used[attribute] = finalizer(namespace,attribute,head)
+ done = done or ok
+ end
end
else
texio.write_nl(string.format("undefined attribute %s",name))
@@ -92,14 +98,17 @@ do
for name, plugin in pairs(shipouts.plugins) do
local attribute = attributes.numbers[name]
if used[attribute] then
- local flusher = plugin.flusher
- if flusher then
- head = flusher(attribute,head,used[attribute])
+ local namespace = plugin.namespace
+ if namespace.enabled then
+ local flusher = plugin.flusher
+ if flusher then
+ head = flusher(namespace,attribute,head,used[attribute])
+ end
end
end
end
end
- input.stop_timing(nodes)
+ input.stop_timing(attributes)
end
return head
end
@@ -132,7 +141,7 @@ states = { }
do
- local glyph, rule, whatsit = node.id('glyph'), node.id('rule'), node.id('whatsit')
+ local glyph, rule, whatsit, hlist, vlist = node.id('glyph'), node.id('rule'), node.id('whatsit'), node.id('hlist'), node.id('vlist')
local current, used, done = 0, { }, false
@@ -140,11 +149,11 @@ do
current, used, done = 0, { }, false
end
- local contains = node.has_attribute
+ local contains, copy = node.has_attribute, node.copy
- function insert(n,stack,previous,head)
+ local function insert(n,stack,previous,head)
if n then
- n = node.copy(n)
+ n = copy(n)
n.next = stack
if previous then
previous.next = n
@@ -156,94 +165,128 @@ do
return stack, previous, head
end
- function states.finalize(what,attribute,head)
- if what.enabled and what.none and current > 0 and head.list then
- local head = head.list
- stack, previous, head = insert(what.none,list,nil,list)
+ function states.finalize(namespace,attribute,head)
+ if current > 0 and namespace.none then
+ if head.id == hlist or head.id == vlist then
+ local stack, previous, head = insert(namespace.none,head.list,nil,head.list)
+ else
+ local stack, previous, head = insert(namespace.none,head,nil,head)
+ end
+ return true, head, true
+ else
+ return false, head, false
end
- return done, head, used
end
---~ function states.process(what,attribute,stack,previous,head) -- one attribute
---~ if what.enabled then
---~ local c = contains(stack,attribute)
---~ if c then
---~ if current ~= c then
---~ local id = stack.id
---~ if id == glyph or id == rule or id == whatsit then
---~ stack, previous, head = insert(what.data[c],stack,previous,head)
---~ current, done, used[c] = c, true, true
---~ end
---~ end
---~ elseif current > 0 then
---~ stack, previous, head = insert(what.none,stack,previous,head)
---~ current, done, used[0] = 0, true, true
---~ end
---~ end
---~ return stack, previous, head
---~ end
-
- function states.process(what,attribute,stack,previous,head) -- one attribute
- if what.enabled then
+ function states.process(namespace,attribute,head,inheritance,default) -- one attribute
+ local trigger = nodes.triggering and nodes.trigger
+ local stack, previous, done, process = head, nil, false, states.process
+ while stack do
local id = stack.id
- if id == glyph or id == rule then -- or id == whatsit then
+ if id == hlist or id == vlist then
+ local content = stack.list
+ if content then
+ local ok = false
+ if trigger and contains(stack,trigger) then
+ local outer = contains(stack,attribute)
+ if outer ~= inheritance then
+ ok, stack.list = process(namespace,attribute,content,inheritance,outer)
+ else
+ ok, stack.list = process(namespace,attribute,content,inheritance,default)
+ end
+ else
+ ok, stack.list = process(namespace,attribute,content,inheritance,default)
+ end
+ done = done or ok
+ end
+ elseif id == glyph or id == rule or id == whatsit then -- special
local c = contains(stack,attribute)
if c then
- if current ~= c then
- stack, previous, head = insert(what.data[c],stack,previous,head)
+ if default and c == inheritance then
+ if current ~= default then
+ local data = namespace.data[default] or namespace.reviver(default)
+ stack, previous, head = insert(data,stack,previous,head)
+ current, done, used[default] = default, true, true
+ end
+ elseif current ~= c then
+ local data = namespace.data[c] or namespace.reviver(c)
+ stack, previous, head = insert(data,stack,previous,head)
current, done, used[c] = c, true, true
end
+ elseif default and inheritance then
+ if current ~= default then
+ local data = namespace.data[default] or namespace.reviver(default)
+ stack, previous, head = insert(data,stack,previous,head)
+ current, done, used[default] = default, true, true
+ end
elseif current > 0 then
- stack, previous, head = insert(what.none,stack,previous,head)
+ stack, previous, head = insert(namespace.none,stack,previous,head)
current, done, used[0] = 0, true, true
end
end
+ previous = stack
+ stack = stack.next
end
- return stack, previous, head
+ return done, head
end
---~ function states.selective(what,attribute,stack,previous,head) -- two attributes
---~ if what.enabled then
---~ local c = contains(stack,attribute)
---~ if c then
---~ if current ~= c then
---~ local id = stack.id
---~ if id == glyph or id == rule then -- or id == whatsit then
---~ stack, previous, head = insert(what.data[c][contains(stack,what.selector) or what.default],stack,previous,head)
---~ current, done, used[c] = c, true, true
---~ end
---~ end
---~ elseif current > 0 then
---~ local id = stack.id
---~ if id == glyph or id == rule then -- or id == whatsit then
---~ stack, previous, head = insert(what.none,stack,previous,head)
---~ current, done, used[0] = 0, true, true
---~ end
---~ end
---~ end
---~ return stack, previous, head
---~ end
+ -- we can force a selector, e.g. document wide color spaces, saves a little
- function states.selective(what,attribute,stack,previous,head) -- two attributes
- if what.enabled then
+ function states.selective(namespace,attribute,head,inheritance,default) -- two attributes
+ local trigger = nodes.triggering and nodes.trigger
+ local stack, previous, done, selective = head, nil, false, states.selective
+ local defaultselector, forcedselector, selector, reviver = namespace.default, namespace.forced, namespace.selector, namespace.reviver
+ local none = namespace.none
+ while stack do
local id = stack.id
- if id == glyph or id == rule then -- or id == whatsit then
+ if id == hlist or id == vlist then
+ local content = stack.list
+ if content then
+ local ok = false
+ if trigger and contains(stack,trigger) then
+ local outer = contains(stack,attribute)
+ if outer ~= inheritance then
+ ok, stack.list = selective(namespace,attribute,content,inheritance,outer)
+ else
+ ok, stack.list = selective(namespace,attribute,content,inheritance,default)
+ end
+ else
+ ok, stack.list = selective(namespace,attribute,content,inheritance,default)
+ end
+ done = done or ok
+ end
+ elseif id == glyph or id == rule or id == whatsit then -- special
local c = contains(stack,attribute)
if c then
- if current ~= c then
- stack, previous, head = insert(what.data[c][contains(stack,what.selector) or what.default],stack,previous,head)
+ if default and c == inheritance then
+ if current ~= default then
+ local data = namespace.data[default] or reviver(default)
+ stack, previous, head = insert(data[forcedselector or contains(stack,selector) or defaultselector],stack,previous,head)
+ current, done, used[default] = default, true, true
+ end
+ elseif current ~= c then
+ local data = namespace.data[c] or reviver(c)
+ stack, previous, head = insert(data[forcedselector or contains(stack,selector) or defaultselector],stack,previous,head)
current, done, used[c] = c, true, true
end
+ elseif default and inheritance then
+ if current ~= default then
+ local data = namespace.data[default] or reviver(default)
+ stack, previous, head = insert(data[forcedselector or contains(stack,selector) or defaultselector],stack,previous,head)
+ current, done, used[default] = default, true, true
+ end
elseif current > 0 then
- stack, previous, head = insert(what.none,stack,previous,head)
+ stack, previous, head = insert(none,stack,previous,head)
current, done, used[0] = 0, true, true
end
end
+ previous = stack
+ stack = stack.next
end
- return stack, previous, head
+ return done, head
end
- collected = { }
+ local collected = { }
function states.collect(str)
collected[#collected+1] = str
@@ -269,24 +312,40 @@ end
-- we also need to store the colorvalues because we need then in mp
-colors = colors or { }
-colors.enabled = true
-colors.data = colors.data or { }
-colors.strings = colors.strings or { }
+colors = colors or { }
+colors.data = colors.data or { }
+colors.values = colors.values or { }
colors.registered = colors.registered or { }
+colors.enabled = true
colors.weightgray = true
colors.attribute = 0
colors.selector = 0
colors.default = 1
+colors.main = nil
-input.storage.register(true,"colors/data", colors.strings, "colors.data")
+-- This is a compromis between speed and simplicity. We used to store the
+-- values and data in one array, which made in neccessary to store the
+-- converters that need node constructor into strings and evaluate them
+-- at runtime (after reading from storage). Think of:
+--
+-- colors.strings = colors.strings or { }
+--
+-- if environment.initex then
+-- colors.strings[color] = "return colors." .. colorspace .. "(" .. table.concat({...},",") .. ")"
+-- end
+--
+-- input.storage.register(true,"colors/data", colors.strings, "colors.data") -- evaluated
+--
+-- We assume that only processcolors are defined in the format.
+
+input.storage.register(false,"colors/values", colors.values, "colors.values")
input.storage.register(false,"colors/registered", colors.registered, "colors.registered")
colors.stamps = {
rgb = "r:%s:%s:%s",
cmyk = "c:%s:%s:%s:%s",
gray = "s:%s",
- spot = "p:%s:%s"
+ spot = "p:%s:%s:%s:%s"
}
colors.models = {
@@ -303,23 +362,23 @@ do
local format = string.format
local concat = table.concat
- local function rgbdata(r,g,b)
- return pdfliteral(format("%s %s %s rg %s %s %s RG",r,g,b,r,g,b))
+ local function rgbdata(r,g,b) -- dodo: backends.pdf.rgbdata
+ return backends.pdf.literal(format("%s %s %s rg %s %s %s RG",r,g,b,r,g,b))
end
local function cmykdata(c,m,y,k)
- return pdfliteral(format("%s %s %s %s k %s %s %s %s K",c,m,y,k,c,m,y,k))
+ return backends.pdf.literal(format("%s %s %s %s k %s %s %s %s K",c,m,y,k,c,m,y,k))
end
local function graydata(s)
- return pdfliteral(format("%s g %s G",s,s))
+ return backends.pdf.literal(format("%s g %s G",s,s))
end
- local function spotdata(n,p) -- name, parent, ratio
+ local function spotdata(n,f,d,p)
if type(p) == "string" then
p = p:gsub(","," ") -- brr misuse of spot
end
- return pdfliteral(format("/%s cs /%s CS %s SCN %s scn",n,n,p,p))
+ return backends.pdf.literal(format("/%s cs /%s CS %s SCN %s scn",n,n,p,p))
end
local function rgbtocmyk(r,g,b)
@@ -349,33 +408,54 @@ do
-- default color space
function colors.gray(s)
- local gray = graydata(s)
- return { gray, gray, gray, gray, 2, s, 0, 0, 0, 0, 0, 0, 1 }
+ return { 2, s, 0, 0, 0, 0, 0, 0, 1 }
end
function colors.rgb(r,g,b)
local s = rgbtogray(r,g,b)
local c, m, y, k = rgbtocmyk(r,g,b)
- local gray, rgb, cmyk = graydata(s), rgbdata(r,g,b), cmykdata(c,m,y,k)
- return { rgb, gray, rgb, cmyk, 3, s, r, g, b, c, m, y, k }
+ return { 3, s, r, g, b, c, m, y, k }
end
function colors.cmyk(c,m,y,k)
local s = cmyktogray(c,m,y,k)
local r, g, b = cmyktorgb(c,m,y,k)
- local gray, rgb, cmyk = graydata(s), rgbdata(r,g,b), cmykdata(c,m,y,k)
- return { cmyk, gray, rgb, cmyk, 4, s, r, g, b, c, m, y, k }
+ return { 4, s, r, g, b, c, m, y, k }
end
- function colors.spot(parent,p) -- parent, ratio
- local spot = spotdata(parent,p)
- if type(p) == "string" and p:find(",") then
- -- use converted replacement (combination color)
- else
- -- todo: map gray, rgb, cmyk onto fraction*parent
+ function colors.spot(parent,f,d,p)
+--~ if type(p) == "string" and p:find(",") then
+--~ -- use converted replacement (combination color)
+--~ else
+--~ -- todo: map gray, rgb, cmyk onto fraction*parent
+--~ end
+ return { 5, .5, .5, .5, .5, 0, 0, 0, .5, parent, f, d, p }
+ end
+
+ function colors.reviver(n)
+ local d = colors.data[n]
+ if not d then
+ local v = colors.values[n]
+ if not v then
+ local gray = graydata(0)
+ d = { gray, gray, gray, gray }
+ logs.report("attributes",string.format("unable to revive color %s",n or "?"))
+ else
+ local kind, gray, rgb, cmyk = v[1], graydata(v[2]), rgbdata(v[3],v[4],v[5]), cmykdata(v[6],v[7],v[8],v[9])
+ if kind == 2 then
+ d = { gray, gray, gray, gray }
+ elseif kind == 3 then
+ d = { rgb, gray, rgb, cmyk }
+ elseif kind == 4 then
+ d = { cmyk, gray, rgb, cmyk }
+ elseif kind == 5 then
+ local spot = spotdata(v[10],v[11],v[12],v[13])
+ d = { spot, gray, rgb, cmyk }
+ end
+ end
+ colors.data[n] = d
end
- local gray, rgb, cmyk = graydata(.5), rgbdata(.5,.5,.5), cmykdata(0,0,0,.5)
- return { spot, gray, rgb, cmyk, 5 }
+ return d
end
function colors.filter(n)
@@ -386,284 +466,197 @@ do
end
--- conversion models
-
function colors.setmodel(attribute,name)
colors.selector = attributes.numbers[attribute]
colors.default = colors.models[name] or 1
return colors.default
end
-function colors.register(attribute, name, colorspace, ...)
+function colors.register(attribute, name, colorspace, ...) -- passing 9 vars is faster
local stamp = string.format(colors.stamps[colorspace], ...)
local color = colors.registered[stamp]
if not color then
- local cd = colors.data
- color = #cd+1
- cd[color] = colors[colorspace](...)
- if environment.initex then
- colors.strings[color] = "return colors." .. colorspace .. "(" .. table.concat({...},",") .. ")"
- end
+ color = #colors.values+1
+ colors.values[color] = colors[colorspace](...)
colors.registered[stamp] = color
+ colors.reviver(color)
+ end
+ if name then
+ attributes.list[attributes.numbers[attribute]][name] = color -- not grouped, so only global colors
end
- attributes.list[attributes.numbers[attribute]][name] = color
return colors.registered[stamp]
end
+function colors.value(id)
+ return colors.values[id]
+end
+
shipouts.plugins.color = {
- initializer = function(...) return states.initialize(colors,...) end,
- finalizer = function(...) return states.finalize (colors,...) end,
- processor = function(...) return states.selective (colors,...) end,
+ namespace = colors,
+ initializer = states.initialize,
+ finalizer = states.finalize ,
+ processor = states.selective ,
+ resolver = function(...) return colors.main end,
+}
+
+-- transparencies
+
+-- for the moment we manage transparencies in the pdf driver because
+-- first we need a nice interface to some pdf things
+
+transparencies = transparencies or { }
+transparencies.registered = transparencies.registered or { }
+transparencies.data = transparencies.data or { }
+transparencies.values = transparencies.values or { }
+transparencies.enabled = true
+transparencies.template = "%s:%s"
+
+input.storage.register(false, "transparencies/registered", transparencies.registered, "transparencies.registered")
+input.storage.register(false, "transparencies/data", transparencies.data, "transparencies.data")
+input.storage.register(false, "transparencies/values", transparencies.values, "transparencies.values")
+
+function transparencies.reference(n)
+ return backends.pdf.literal(string.format("/Tr%s gs",n))
+end
+
+transparencies.none = transparencies.reference(0)
+
+function transparencies.register(name,...)
+ local stamp = string.format(transparencies.template, ...)
+ local n = transparencies.registered[stamp]
+ if not n then
+ n = #transparencies.data+1
+ transparencies.data[n] = transparencies.reference(n)
+ transparencies.values[n] = { ... }
+ transparencies.registered[stamp] = n
+ states.collect(string.format("\\presetPDFtransparency{%s}{%s}",...)) -- too many, but experimental anyway
+ end
+ return transparencies.registered[stamp]
+end
+
+function transparencies.value(id)
+ return transparencies.values[id]
+end
+
+shipouts.plugins.transparency = {
+ namespace = transparencies,
+ initializer = states.initialize,
+ finalizer = states.finalize ,
+ processor = states.process ,
}
--- overprint / knockout
-overprints = { enabled = true , data = { } }
+overprints = overprints or { }
+overprints.data = overprints.data or { }
+overprints.enabled = true
+
+overprints.data[1] = backends.pdf.literal(string.format("/GSoverprint gs"))
+overprints.data[2] = backends.pdf.literal(string.format("/GSknockout gs"))
-overprints.none = pdfliteral(string.format("/GSoverprint gs"))
-overprints.data[1] = pdfliteral(string.format("/GSknockout gs"))
+overprints.none = overprints.data[1]
overprints.registered = {
- overprint = 0,
- knockout = 1,
+ overprint = 1,
+ knockout = 2,
}
function overprints.register(stamp)
+-- states.collect(tex.sprint(tex.ctxcatcodes,"\\initializePDFoverprint")) -- to be testd
return overprints.registered[stamp] or overprints.registered.overprint
end
shipouts.plugins.overprint = {
- initializer = function(...) return states.initialize(overprints,...) end,
- finalizer = function(...) return states.finalize (overprints,...) end,
- processor = function(...) return states.process (overprints,...) end,
+ namespace = overprints,
+ initializer = states.initialize,
+ finalizer = states.finalize ,
+ processor = states.process ,
}
--- negative / positive
-negatives = { enabled = true, data = { } }
+negatives = netatives or { }
+negatives.data = negatives.data or { }
+negatives.enabled = true
-negatives.none = pdfliteral(string.format("/GSpositive gs"))
-negatives.data[1] = pdfliteral(string.format("/GSnegative gs"))
+negatives.data[1] = backends.pdf.literal(string.format("/GSpositive gs"))
+negatives.data[2] = backends.pdf.literal(string.format("/GSnegative gs"))
+
+negatives.none = negatives.data[1]
negatives.registered = {
- positive = 0,
- negative = 1,
+ positive = 1,
+ negative = 2,
}
function negatives.register(stamp)
+-- states.collect(tex.sprint(tex.ctxcatcodes,"\\initializePDFnegative")) -- to be testd
return negatives.registered[stamp] or negatives.registered.positive
end
shipouts.plugins.negative = {
- initializer = function(...) return states.initialize(negatives,...) end,
- finalizer = function(...) return states.finalize (negatives,...) end,
- processor = function(...) return states.process (negatives,...) end,
+ namespace = negatives,
+ initializer = states.initialize,
+ finalizer = states.finalize,
+ processor = states.process,
}
-- effects
-effects = { enabled = true, data = { } }
-
-effects.none = pdfliteral(string.format("0 Tr"))
-effects.data[1] = pdfliteral(string.format("1 Tr"))
-effects.data[2] = pdfliteral(string.format("2 Tr"))
-effects.data[3] = pdfliteral(string.format("3 Tr"))
+effects = effects or { }
+effects.data = effects.data or { }
+effects.registered = effects.registered or { }
+effects.enabled = true
+effects.stamp = "%s:%s:%s"
+
+input.storage.register(false, "effects/registered", effects.registered, "effects.registered")
+input.storage.register(false, "effects/data", effects.data, "effects.data")
+
+function effects.register(effect,stretch,rulethickness)
+ local stamp = string.format(effects.stamp,effect,stretch,rulethickness)
+ local n = effects.registered[stamp]
+ if not n then
+ n = #effects.data+1
+ effects.data[n] = effects.reference(effect,stretch,rulethickness)
+ effects.registered[stamp] = n
+ -- states.collect("") -- nothing
+ end
+ return effects.registered[stamp]
+end
-effects.registered = {
- normal = 0,
- inner = 0,
- outer = 1,
- both = 2,
- hidden = 3,
+backends.pdf.effects = {
+ normal = 1,
+ inner = 1,
+ outer = 2,
+ both = 3,
+ hidden = 4,
}
-function effects.register(stamp)
- return effects.registered[stamp] or effects.registered.normal
+function effects.reference(effect,stretch,rulethickness) -- will move, test code, we will develop a proper model for that
+ effect = backends.pdf.effects[effects] or backends.pdf.effects['normal']
+ if stretch > 0 then
+ stretch = stretch .. " w "
+ else
+ stretch = ""
+ end
+ if rulethickness > 0 then
+ rulethickness = number.dimenfactors["bp"]*rulethickness.. " Tc "
+ else
+ rulethickness = ""
+ end
+ return backends.pdf.literal(string.format("%s%s%s Tr",stretch,rulethickness,effect)) -- watch order
end
+effects.none = effects.reference(effect,0,0)
+
shipouts.plugins.effect = {
- initializer = function(...) return states.initialize(effects,...) end,
- finalizer = function(...) return states.finalize (effects,...) end,
- processor = function(...) return states.process (effects,...) end,
+ namespace = effects,
+ initializer = states.initialize,
+ finalizer = states.finalize ,
+ processor = states.process ,
}
-- layers
--~ /OC /somename BDC
--~ EMC
-
--- transparencies
-
--- for the moment we manage transparencies in the pdf driver because
--- first we need a nice interface to some pdf things
-
-transparencies = {
- enabled = true,
- data = { },
- registered = { },
- hack = { }
-}
-
-input.storage.register(false, "transparencies/registed", transparencies.registered, "transparencies.registered")
-input.storage.register(false, "transparencies/data", transparencies.data, "transparencies.data")
-input.storage.register(false, "transparencies/hack", transparencies.hack, "transparencies.hack")
-
-function transparencies.reference(n)
- return pdfliteral(string.format("/Tr%s gs",n))
-end
-
-transparencies.none = transparencies.reference(0)
-
-transparencies.stamp = "%s:%s"
-
-function transparencies.register(...)
- local stamp = string.format(transparencies.stamp, ...)
- if not transparencies.registered[stamp] then
- local n = #transparencies.data+1
- transparencies.data[n] = transparencies.reference(n)
- transparencies.registered[stamp] = n
- states.collect(string.format("\\presetPDFtransparency{%s}{%s}",...)) -- too many, but experimental anyway
- end
- return transparencies.registered[stamp]
-end
-
-shipouts.plugins.transparency = {
- initializer = function(...) return states.initialize(transparencies,...) end,
- finalizer = function(...) return states.finalize (transparencies,...) end,
- processor = function(...) return states.process (transparencies,...) end,
-}
-
---~ shipouts.plugins.transparency.flusher = function(attribute,head,used)
---~ local max = 0
---~ for k,v in pairs(used) do
---~ end
---~ return head
---~ end
-
---~ from the time that node lists were tables and not userdata ...
---~
---~ local function do_collapse_page(stack,existing_t)
---~ if stack then
---~ local t = existing_t or { }
---~ for _, node in ipairs(stack) do
---~ if node then
---~ local kind = node[1]
---~ node[3] = nil
---~ if kind == 'hlist' or kind == 'vlist' then
---~ node[8] = do_collapse_page(node[8]) -- maybe here check for nil
---~ t[#t+1] = node
---~ elseif kind == 'inline' then -- appending literals cost too much time
---~ local nodes = node[4]
---~ if #nodes == 1 then
---~ t[#t+1] = nodes[1]
---~ else
---~ do_collapse_page(nodes,t)
---~ end
---~ else
---~ t[#t+1] = node
---~ end
---~ end
---~ end
---~ return t
---~ else
---~ return nil
---~ end
---~ end
---~
---~ local function do_process_page(attribute,processor,stack)
---~ if stack then
---~ for i, node in ipairs(stack) do
---~ if node then
---~ local kind = node[1]
---~ if kind == 'hlist' or kind == "vlist" then
---~ local content = node[8]
---~ if not content then
---~ -- nil node
---~ elseif type(content) == "table" then
---~ node[8] = do_process_page(attribute,processor,content)
---~ else
---~ node[8] = do_process_page(attribute,processor,tex.get_node_list(content))
---~ end
---~ elseif kind == 'inline' then
---~ node[4] = do_process_page(attribute,processor,node[4])
---~ else
---~ processor(attribute,stack,i,node,kind)
---~ end
---~ end
---~ end
---~ end
---~ return stack
---~ end
---~
---~ function nodes.process_page(stack,...)
---~ if stack then
---~ input.start_timing(nodes)
---~ local done, used = false, { }
---~ for name, plugin in pairs(shipouts.plugins) do
---~ local attribute = attributes.numbers[name]
---~ if attribute then
---~ local initializer = plugin.initializer
---~ local processor = plugin.processor
---~ local finalizer = plugin.finalizer
---~ if initializer then
---~ initializer(attribute,stack)
---~ end
---~ if processor then
---~ do_process_page(attribute,processor,stack)
---~ end
---~ if finalizer then
---~ local ok
---~ ok, used[attribute] = finalizer(attribute,stack)
---~ done = done or ok
---~ end
---~ else
---~ texio.write_nl(string.format("undefined attribute %s",name))
---~ end
---~ end
---~ if done then
---~ stack = do_collapse_page(stack)
---~ for name, plugin in pairs(shipouts.plugins) do
---~ local attribute = attributes.numbers[name]
---~ if used[attribute] then
---~ local flusher = plugin.flusher
---~ if flusher then
---~ flusher(attribute,stack,used[attribute])
---~ end
---~ end
---~ end
---~ else
---~ stack = true
---~ end
---~ input.stop_timing(nodes)
---~ end
---~ return stack
---~ end
---~
---~ function states.finalize(what,attribute,stack)
---~ if what.enabled then
---~ if current > 0 then
---~ local list = stack
---~ if #stack == 1 then
---~ list = stack[#stack][8]
---~ end
---~ list[#list+1], current, done, used[0] = what.none, 0, true, true
---~ end
---~ end
---~ return done, used
---~ end
---~
---~ function states.process(what,attribute,stack,i,node,kind)
---~ if what.enabled then
---~ local a = node[3]
---~ if a then
---~ local c = a[attribute]
---~ if c then
---~ if current ~= c and (kind == 'glyph' or kind == 'rule') then
---~ stack[i], current, done, used[c] = nodes.inline(what.data[c], node), c, true, true
---~ end
---~ elseif current > 0 then
---~ stack[i], current, done, used[0] = nodes.inline(what.none, node), 0, true, true
---~ end
---~ end
---~ end
---~ end