if not modules then modules = { } end modules ['colo-ini'] = {
version = 1.000,
comment = "companion to colo-ini.tex",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright = "PRAGMA ADE / ConTeXt Development Team",
license = "see context related readme files"
}
-- split_settings -> aux.settings_to_hash
-- for the moment this looks messy but we're waiting for a pdf backend interface
--
-- code collected here will move and be adapted
--
-- some pdf related code can go away
-- spec-pdf.lua
-- todo: %s -> %f
backends = backends or { }
backends.pdf = backends.pdf or { }
backend = backends.pdf
local texsprint, format, concat = tex.sprint, string.format, table.concat
local s_template_g = "\\dodoPDFregistergrayspotcolor{%s}{%s}{%s}{%s}{%s}" -- n f d p s (p can go away)
local s_template_r = "\\dodoPDFregisterrgbspotcolor {%s}{%s}{%s}{%s}{%s}{%s}{%s}" -- n f d p r g b
local s_template_c = "\\dodoPDFregistercmykspotcolor{%s}{%s}{%s}{%s}{%s}{%s}{%s}{%s}" -- n f d p c m y k
function backends.pdf.registergrayspotcolor(n,f,d,p,s) states.collect(s_template_g:format(n,f,d,p,s)) end
function backends.pdf.registerrgbspotcolor (n,f,d,p,r,g,b) states.collect(s_template_r:format(n,f,d,p,r,g,b)) end
function backends.pdf.registercmykspotcolor(n,f,d,p,c,m,y,k) states.collect(s_template_c:format(n,f,d,p,c,m,y,k)) end
local m_template_g = "\\doPDFregistergrayindexcolor{%s}{%s}{%s}{%s}{%s}" -- n f d p s (p can go away)
local m_template_r = "\\doPDFregisterrgbindexcolor {%s}{%s}{%s}{%s}{%s}{%s}{%s}" -- n f d p r g b
local m_template_c = "\\doPDFregistercmykindexcolor{%s}{%s}{%s}{%s}{%s}{%s}{%s}{%s}" -- n f d p c m y k
function backends.pdf.registergrayindexcolor(n,f,d,p,s) states.collect(m_template_g:format(n,f,d,p,s)) end
function backends.pdf.registerrgbindexcolor (n,f,d,p,r,g,b) states.collect(m_template_r:format(n,f,d,p,r,g,b)) end
function backends.pdf.registercmykindexcolor(n,f,d,p,c,m,y,k) states.collect(m_template_c:format(n,f,d,p,c,m,y,k)) end
local s_template_e = "\\doPDFregisterspotcolorname{%s}{%s}" -- name, e
function backends.pdf.registerspotcolorname(name,e)
if e and e ~= "" then
texsprint(tex.ctxcatcodes,format(s_template_e,name,e)) -- todo in new backend: e:gsub(" ","#20")
end
end
ctx = ctx or { }
ctx.aux = ctx.aux or { }
local a_l_c_template = "\\setevalue{(ca:%s)}{%s}" ..
"\\setevalue{(cs:%s)}{\\dosetattribute{color}{%s}}"
local a_g_c_template = "\\setxvalue{(ca:%s)}{%s}" ..
"\\setxvalue{(cs:%s)}{\\dosetattribute{color}{%s}}"
local f_l_c_template = "\\setvalue {(ca:%s)}{\\doinheritca{%s}}" ..
"\\setvalue {(cs:%s)}{\\doinheritcs{%s}}"
local f_g_c_template = "\\setgvalue{(ca:%s)}{\\doinheritca{%s}}" ..
"\\setgvalue{(cs:%s)}{\\doinheritcs{%s}}"
local r_l_c_template = "\\letbeundefined{(ca:%s)}" ..
"\\letbeundefined{(cs:%s)}"
local r_g_c_template = "\\global\\letbeundefined{(ca:%s)}" ..
"\\global\\letbeundefined{(cs:%s)}"
local a_l_t_template = "\\setevalue{(ta:%s)}{%s}" ..
"\\setevalue{(ts:%s)}{\\dosetattribute{transparency}{%s}}"
local a_g_t_template = "\\setxvalue{(ta:%s)}{%s}" ..
"\\setxvalue{(ts:%s)}{\\dosetattribute{transparency}{%s}}"
local f_l_t_template = "\\setvalue {(ta:%s)}{\\doinheritta{%s}}" ..
"\\setvalue {(ts:%s)}{\\doinheritts{%s}}"
local f_g_t_template = "\\setgvalue{(ta:%s)}{\\doinheritta{%s}}" ..
"\\setgvalue{(ts:%s)}{\\doinheritts{%s}}"
local r_l_t_template = "\\letbeundefined{(ta:%s)}" ..
"\\letbeundefined{(ts:%s)}"
local r_g_t_template = "\\global\\letbeundefined{(ta:%s)}" ..
"\\global\\letbeundefined{(ts:%s)}"
function ctx.aux.definecolor(name, ca, global)
if ca and ca > 0 then
if global then
texsprint(tex.ctxcatcodes,a_g_c_template:format(name, ca, name, ca))
else
texsprint(tex.ctxcatcodes,a_l_c_template:format(name, ca, name, ca))
end
else
if global then
texsprint(tex.ctxcatcodes,r_g_c_template:format(name, name))
else
texsprint(tex.ctxcatcodes,r_l_c_template:format(name, name))
end
end
end
function ctx.aux.inheritcolor(name, ca, global)
if ca and ca ~= "" then
if global then
texsprint(tex.ctxcatcodes,f_g_c_template:format(name, ca, name, ca))
else
texsprint(tex.ctxcatcodes,f_l_c_template:format(name, ca, name, ca))
end
else
if global then
texsprint(tex.ctxcatcodes,r_g_c_template:format(name, name))
else
texsprint(tex.ctxcatcodes,r_l_c_template:format(name, name))
end
end
end
function ctx.aux.definetransparent(name, ta, global)
if ta and ta > 0 then
if global then
texsprint(tex.ctxcatcodes,a_g_t_template:format(name, ta, name, ta))
else
texsprint(tex.ctxcatcodes,a_l_t_template:format(name, ta, name, ta))
end
else
if global then
texsprint(tex.ctxcatcodes,r_g_t_template:format(name, name))
else
texsprint(tex.ctxcatcodes,r_l_t_template:format(name, name))
end
end
end
function ctx.aux.inherittransparent(name, ta, global)
if ta and ta ~= "" then
if global then
texsprint(tex.ctxcatcodes,f_g_t_template:format(name, ta, name, ta))
else
texsprint(tex.ctxcatcodes,f_l_t_template:format(name, ta, name, ta))
end
else
if global then
texsprint(tex.ctxcatcodes,r_g_t_template:format(name, name))
else
texsprint(tex.ctxcatcodes,r_l_t_template:format(name, name))
end
end
end
local transparent = {
none = 0,
normal = 1,
multiply = 2,
screen = 3,
overlay = 4,
softlight = 5,
hardlight = 6,
colordodge = 7,
colorburn = 8,
darken = 9,
lighten = 10,
difference = 11,
exclusion = 12,
}
-- By coupling we are downward compatible. When we decouple we need to do more tricky
-- housekeeping (e.g. persist color independent transparencies when color bound ones
-- are nil.
ctx.couplecolors = true
function ctx.definetransparency(name,n)
transparent[name] = n
end
local registered = { }
local function registerspotcolor(parent,name,parentnumber,e,f,d,p)
if not registered[parentnumber] then
local v = colors.values[parentnumber]
if v then
local kind = v[1]
kind = colors.default -- else problems with shading etc
if kind == 2 then -- name noffractions names p's r g b
backend.registergrayspotcolor(parent,f,d,p,v[2])
elseif kind == 3 then
backend.registerrgbspotcolor (parent,f,d,p,v[3],v[4],v[5])
elseif kind == 4 then
backend.registercmykspotcolor(parent,f,d,p,v[6],v[7],v[8],v[9])
end
backends.pdf.registerspotcolorname(parent,e)
end
registered[parentnumber] = true
end
end
local function registermultitonecolor(parent,name,parentnumber,e,f,d,p) -- same as spot but different template
if not registered[parentnumber] then
local v = colors.values[parentnumber]
if v then
local kind = v[1]
if kind == 2 then
backend.registergrayindexcolor(parent,f,d,p,v[2])
elseif kind == 3 then
backend.registerrgbindexcolor (parent,f,d,p,v[3],v[4],v[5])
elseif kind == 4 then
backend.registercmykindexcolor(parent,f,d,p,v[6],v[7],v[8],v[9])
end
end
registered[parentnumber] = true
end
end
function ctx.definesimplegray(name,s)
return colors.register('color',name,'gray',s) -- we still need to get rid of 'color'
end
function ctx.defineprocesscolor(name,str,global,freeze) -- still inconsistent color vs transparent
local t = str:split_settings()
if t then
if t.h then
local r, g, b = (t.h .. "000000"):match("(..)(..)(..)")
ctx.aux.definecolor(name, colors.register('color',name,'rgb',(tonumber(r,16) or 0)/256,(tonumber(g,16) or 0)/256,(tonumber(b,16) or 0)/256 ), global)
elseif t.r or t.g or t.b then
ctx.aux.definecolor(name, colors.register('color',name,'rgb', tonumber(t.r) or 0, tonumber(t.g) or 0, tonumber(t.b) or 0 ), global)
elseif t.c or t.m or t.y or t.k then
ctx.aux.definecolor(name, colors.register('color',name,'cmyk',tonumber(t.c) or 0, tonumber(t.m) or 0, tonumber(t.y) or 0, tonumber(t.k) or 0), global)
else
ctx.aux.definecolor(name, colors.register('color',name,'gray',tonumber(t.s) or 0), global)
end
if t.a and t.t then
ctx.aux.definetransparent(name, transparencies.register(name,transparent[t.a] or tonumber(t.a) or 1,tonumber(t.t) or 1), global)
elseif ctx.couplecolors then
-- ctx.aux.definetransparent(name, transparencies.register(nil, 1, 1), global) -- can be sped up
ctx.aux.definetransparent(name, 0, global) -- can be sped up
end
elseif freeze then
local ca = attributes.list[attributes.numbers['color']] [str]
local ta = attributes.list[attributes.numbers['transparency']][str]
if ca then
ctx.aux.definecolor(name, ca, global)
end
if ta then
ctx.aux.definetransparent(name, ta, global)
end
else
ctx.aux.inheritcolor(name, str, global)
ctx.aux.inherittransparent(name, str, global)
-- if global and str ~= "" then -- For Peter Rolf who wants access to the numbers in Lua. (Currently only global is supported.)
-- attributes.list[attributes.numbers['color']] [name] = attributes.list[attributes.numbers['color']] [str] or -1 -- reset
-- attributes.list[attributes.numbers['transparency']][name] = attributes.list[attributes.numbers['transparency']][str] or -1 -- reset
-- end
end
end
function ctx.isblack(ca) -- maybe commands
local cv = ca > 0 and colors.value(ca)
return (cv and cv[2] == 0) or false
end
-- function ctx.aux.colorattribute(name)
-- local al = attributes.list[attributes.numbers['color']]
-- return al[name] or 0
-- end
-- function ctx.aux.transparencyattribute(name)
-- local al = attributes.list[attributes.numbers['transparency']]
-- return al[name] or 0
-- end
function ctx.definespotcolor(name,parent,str,global)
if parent == "" or parent:find("=") then
ctx.registerspotcolor(name, parent)
elseif name ~= parent then
local cp = attributes.list[attributes.numbers['color']][parent]
if cp then
local t = str:split_settings()
if t then
t.p = tonumber(t.p) or 1
registerspotcolor(parent, name, cp, t.e, 1, "", t.p) -- p not really needed, only diagnostics
if name and name ~= "" then
ctx.aux.definecolor(name, colors.register('color',name,'spot', parent, 1, "", t.p), true)
if t.a and t.t then
ctx.aux.definetransparent(name, transparencies.register(name,transparent[t.a] or tonumber(t.a) or 1,tonumber(t.t) or 1), global)
elseif ctx.couplecolors then
--~ ctx.aux.definetransparent(name, transparencies.register(nil, 1, 1), global) -- can be sped up
ctx.aux.definetransparent(name, 0, global) -- can be sped up
end
end
end
end
end
end
function ctx.registerspotcolor(parent, str)
local cp = attributes.list[attributes.numbers['color']][parent]
if cp then
local e = ""
if str then
local t = str:split_settings()
e = (t and t.e) or ""
end
registerspotcolor(parent, "dummy", cp, e, 1, "", 1) -- p not really needed, only diagnostics
end
end
function ctx.definemultitonecolor(name,multispec,colorspec,selfspec)
local dd, pp, nn = { }, { }, { }
for k,v in multispec:gmatch("(%a+)=([^%,]*)") do
dd[#dd+1] = k
pp[#pp+1] = v
nn[#nn+1] = k
nn[#nn+1] = format("%1.3g",tonumber(v))
end
--~ v = tonumber(v) * p
local nof = #dd
if nof > 0 then
dd, pp, nn = concat(dd,','), concat(pp,','), concat(nn,'_')
local parent = (nn:lower()):gsub("[^%d%a%.]+","_")
ctx.defineprocesscolor(parent,colorspec..","..selfspec,true,true)
local cp = attributes.list[attributes.numbers['color']][parent]
if cp then
registerspotcolor (parent, name, cp, "", nof, dd, pp)
registermultitonecolor(parent, name, cp, "", nof, dd, pp)
ctx.aux.definecolor(name, colors.register('color', name, 'spot', parent, nof, dd, pp), true)
local t = selfspec:split_settings()
if t and t.a and t.t then
ctx.aux.definetransparent(name, transparencies.register(name,transparent[t.a] or tonumber(t.a) or 1,tonumber(t.t) or 1), global)
elseif ctx.couplecolors then
-- ctx.aux.definetransparent(name, transparencies.register(nil, 1, 1), global) -- can be sped up
ctx.aux.definetransparent(name, 0, global) -- can be sped up
end
end
end
end
function ctx.mpcolor(model,ca,ta,default)
local cv = colors.value(ca) -- faster when direct colors.values[ca]
if cv then
local tv = transparencies.value(ta)
if model == 1 then
model = cv[1]
end
if tv then
if model == 2 then
return format("transparent(%s,%s,(%s,%s,%s))",tv[1],tv[2],cv[3],cv[4],cv[5])
elseif model == 3 then
return format("transparent(%s,%s,(%s,%s,%s))",tv[1],tv[2],cv[3],cv[4],cv[5])
elseif model == 4 then
return format("transparent(%s,%s,cmyk(%s,%s,%s,%s))",tv[1],tv[2],cv[6],cv[7],cv[8],cv[9])
else
return format("transparent(%s,%s,multitonecolor(\"%s\",%s,\"%s\",\"%s\"))",tv[1],tv[2],cv[10],cv[11],cv[12],cv[13])
end
else
if model == 2 then
return format("(%s,%s,%s)",cv[3],cv[4],cv[5])
elseif model == 3 then
return format("(%s,%s,%s)",cv[3],cv[4],cv[5])
elseif model == 4 then
return format("cmyk(%s,%s,%s,%s)",cv[6],cv[7],cv[8],cv[9])
else
return format("multitonecolor(\"%s\",%s,\"%s\",\"%s\")",cv[10],cv[11],cv[12],cv[13])
end
end
else
default = default or 0 -- rgb !
return format("(%s,%s,%s)",default,default,default)
end
end
function ctx.formatcolor(ca,separator)
local cv = colors.value(ca)
if cv then
local model = cv[1]
if model == 2 then
return tostring(cv[2])
elseif model == 3 then
return concat(cv,separator,3,5)
elseif model == 4 then
return concat(cv,separator,6,9)
else
return tostring(cv[13])
end
else
return tostring(0)
end
end
function ctx.formatgray(ca,separator)
local cv = colors.value(ca)
if cv then
return tostring(cv[2])
else
return tostring(0)
end
end
function ctx.colorcomponents(ca)
local cv = colors.value(ca)
if cv then
local model = cv[1]
if model == 2 then
return format("s=%1.3f",cv[2])
elseif model == 3 then
return format("r=%1.3f g=%1.3f b=%1.3f",cv[3],cv[4],cv[5])
elseif model == 4 then
return format("c=%1.3f m=%1.3f y=%1.3f k=%1.3f",cv[6],cv[7],cv[8],cv[9])
elseif type(cv[13]) == "string" then
return format("p=%s",cv[13])
else
return format("p=%1.3f",cv[13])
end
else
return ""
end
end
function ctx.transparencycomponents(ta)
local tv = transparencies.value(ta)
if tv then
return format("a=%1.3f t=%1.3f",tv[1],tv[2])
else
return ""
end
end
function ctx.pdfcolor(model,ca,default) -- todo: use gray when no color
local cv = colors.value(ca)
if cv then
if model == 1 then
model = cv[1]
end
if model == 2 then
local s = cv[2]
return format("%s g %s G",s,s)
elseif model == 3 then
local r, g, b = cv[3], cv[4], cv[5]
return format("%s %s %s rg %s %s %s RG",r,g,b,r,g,b)
elseif model == 4 then
local c, m, y, k = cv[6],cv[7],cv[8],cv[9]
return format("%s %s %s %s k %s %s %s %s K",c,m,y,k,c,m,y,k)
else
local n,f,d,p = cv[10],cv[11],cv[12],cv[13]
if type(p) == "string" then
p = p:gsub(","," ") -- brr misuse of spot
end
return format("/%s cs /%s CS %s SCN %s scn",n,n,p,p)
end
else
return format("%s g %s G",default or 0,default or 0)
end
end
function ctx.pdfcolorvalue(model,ca,default)
local cv = colors.value(ca)
if cv then
if model == 1 then
model = cv[1]
end
if model == 2 then
return format("%s",cv[2])
elseif model == 3 then
return format("%s %s %s",cv[3],cv[4],cv[5])
elseif model == 4 then
return format("%s %s %s %s",cv[6],cv[7],cv[8],cv[9])
else
return format("%s",cv[13])
end
else
return format("%s",default or 0)
end
end
function ctx.fdfcolor(model,ca,default)
local cv = colors.value(ca)
if cv then
if model == 1 then
model = cv[1]
end
if model == 2 then
return format("[%s]",cv[2])
elseif model == 3 then
return format("[%s %s %s]",cv[3],cv[4],cv[5])
elseif model == 4 then
return format("[%s %s %s %s]",cv[6],cv[7],cv[8],cv[9])
elseif model == 4 then
return format("[%s]",cv[13])
end
else
return format("[%s]",default or 0)
end
end
function ctx.pdfcolorspace(model,ca)
local cv = colors.value(ca)
if cv then
if model == 1 then
model = cv[1]
end
if model == 2 then
return "DeviceGray"
elseif model == 3 then
return "DeviceRGB"
elseif model == 4 then
return "DeviceCMYK"
end
end
return "DeviceGRAY"
end
function ctx.spotcolorname(ca,default)
local cv, v = colors.value(ca), "unknown"
if cv and cv[1] == 5 then
v = cv[10]
end
return tostring(v)
end
function ctx.spotcolorvalue(ca,default)
local cv, v = colors.value(ca), 0
if cv and cv[1] == 5 then
v = cv[13]
end
return tostring(v)
end
-- unfortunately we have \cs's here but this will go anyway once we have mplib and such
function ctx.resolvempgraycolor(csa,csb,model,s)
local ca = colors.register('color',nil,'gray',s)
texsprint(tex.ctxcatcodes,format("\\setxvalue{%s}{%s}",csa,ctx.pdfcolorvalue(model,ca)))
texsprint(tex.ctxcatcodes,format("\\setxvalue{%s}{%s}",csb,ctx.pdfcolorspace(model,ca)))
end
function ctx.resolvemprgbcolor(csa,csb,model,r,g,b)
local ca = colors.register('color',nil,'rgb',r,g,b)
texsprint(tex.ctxcatcodes,format("\\setxvalue{%s}{%s}",csa,ctx.pdfcolorvalue(model,ca)))
texsprint(tex.ctxcatcodes,format("\\setxvalue{%s}{%s}",csb,ctx.pdfcolorspace(model,ca)))
end
function ctx.resolvempcmykcolor(csa,csb,model,c,m,y,k)
local ca = colors.register('color',nil,'cmyk',c,m,y,k)
texsprint(tex.ctxcatcodes,format("\\setxvalue{%s}{%s}",csa,ctx.pdfcolorvalue(model,ca)))
texsprint(tex.ctxcatcodes,format("\\setxvalue{%s}{%s}",csb,ctx.pdfcolorspace(model,ca)))
end
function ctx.resolvempspotcolor(csa,csb,model,n,f,d,p)
local ca = colors.register('color',nil,'spot',n,f,d,p)
texsprint(tex.ctxcatcodes,format("\\setxvalue{%s}{%s}",csa,ctx.pdfcolorvalue(model,ca)))
texsprint(tex.ctxcatcodes,format("\\setxvalue{%s}{%s}",csb,ctx.pdfcolorspace(model,ca)))
end
-- literals needed to inject code in the mp stream, we cannot use attributes there
-- since literals may have qQ's, much may go away once we have mplib code in place
local intransparency = false
function ctx.pdfrgbliteral(model,r,g,b)
texsprint(tex.ctxcatcodes,format("\\pdfliteral{%s}",ctx.pdfcolor(model,colors.register('color',nil,'rgb',r,g,b))))
end
function ctx.pdfcmykliteral(model,c,m,y,k)
texsprint(tex.ctxcatcodes,format("\\pdfliteral{%s}",ctx.pdfcolor(model,colors.register('color',nil,'cmyk',c,m,y,k))))
end
function ctx.pdfgrayliteral(model,s)
texsprint(tex.ctxcatcodes,format("\\pdfliteral{%s}",ctx.pdfcolor(model,colors.register('color',nil,'gray',s))))
end
function ctx.pdfspotliteral(model,n,f,d,p)
texsprint(tex.ctxcatcodes,format("\\pdfliteral{%s}",ctx.pdfcolor(model,colors.register('color',nil,'spot',n,f,d,p)))) -- incorrect
end
function ctx.pdftransparencyliteral(a,t)
intransparency = true
texsprint(tex.ctxcatcodes,format("\\pdfliteral{/Tr%s gs}",transparencies.register(nil,a,t)))
end
function ctx.pdffinishtransparency()
if intransparency then
intransparency = false
texsprint(tex.ctxcatcodes,"\\pdfliteral{/Tr0 gs}") -- we happen to know this -)
end
end