summaryrefslogtreecommitdiff
path: root/tex/context/base/lpdf-col.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-col.lua
parentf5aed2e51223c36c84c5f25a6cad238b2af59087 (diff)
downloadcontext-8d8d528d2ad52599f11250cfc567fea4f37f2a8b.tar.gz
2016-01-12 16:26:00
Diffstat (limited to 'tex/context/base/lpdf-col.lua')
-rw-r--r--tex/context/base/lpdf-col.lua735
1 files changed, 0 insertions, 735 deletions
diff --git a/tex/context/base/lpdf-col.lua b/tex/context/base/lpdf-col.lua
deleted file mode 100644
index 877c01a1c..000000000
--- a/tex/context/base/lpdf-col.lua
+++ /dev/null
@@ -1,735 +0,0 @@
-if not modules then modules = { } end modules ['lpdf-col'] = {
- 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"
-}
-
-local type, next, tostring, tonumber = type, next, tostring, tonumber
-local char, byte, format, gsub, rep, gmatch = string.char, string.byte, string.format, string.gsub, string.rep, string.gmatch
-local concat = table.concat
-local round = math.round
-local formatters = string.formatters
-
-local backends, lpdf, nodes = backends, lpdf, nodes
-
-local allocate = utilities.storage.allocate
-local formatters = string.formatters
-
-local nodeinjections = backends.pdf.nodeinjections
-local codeinjections = backends.pdf.codeinjections
-local registrations = backends.pdf.registrations
-
-local nodepool = nodes.pool
-local register = nodepool.register
-local pdfliteral = nodepool.pdfliteral
-
-local pdfconstant = lpdf.constant
-local pdfstring = lpdf.string
-local pdfdictionary = lpdf.dictionary
-local pdfarray = lpdf.array
-local pdfreference = lpdf.reference
-local pdfverbose = lpdf.verbose
-local pdfflushobject = lpdf.flushobject
-local pdfdelayedobject = lpdf.delayedobject
-local pdfflushstreamobject = lpdf.flushstreamobject
-
-local pdfshareobjectreference = lpdf.shareobjectreference
-
-local addtopageattributes = lpdf.addtopageattributes
-local adddocumentcolorspace = lpdf.adddocumentcolorspace
-local adddocumentextgstate = lpdf.adddocumentextgstate
-
-local colors = attributes.colors
-local transparencies = attributes.transparencies
-local registertransparancy = transparencies.register
-local registercolor = colors.register
-local colorsvalue = colors.value
-local transparenciesvalue = transparencies.value
-local forcedmodel = colors.forcedmodel
-local getpagecolormodel = colors.getpagecolormodel
-
-local c_transparency = pdfconstant("Transparency")
-
-local f_gray = formatters["%.3F g %.3F G"]
-local f_rgb = formatters["%.3F %.3F %.3F rg %.3F %.3F %.3F RG"]
-local f_cmyk = formatters["%.3F %.3F %.3F %.3F k %.3F %.3F %.3F %.3F K"]
-local f_spot = formatters["/%s cs /%s CS %s SCN %s scn"]
-local f_tr = formatters["Tr%s"]
-local f_cm = formatters["q %F %F %F %F %F %F cm"]
-local f_effect = formatters["%s Tc %s w %s Tr"]
-local f_tr_gs = formatters["/Tr%s gs"]
-local f_num_1 = tostring
-local f_num_2 = formatters["%s %s"]
-local f_num_3 = formatters["%s %s %s"]
-local f_num_4 = formatters["%s %s %s %s"]
-
-local report_color = logs.reporter("colors","backend")
-
--- page groups (might move to lpdf-ini.lua)
-
-local colorspaceconstants = allocate { -- v_none is ignored
- gray = pdfconstant("DeviceGray"),
- rgb = pdfconstant("DeviceRGB"),
- cmyk = pdfconstant("DeviceCMYK"),
- all = pdfconstant("DeviceRGB"), -- brr
-}
-
-local transparencygroups = { }
-
-lpdf.colorspaceconstants = colorspaceconstants
-lpdf.transparencygroups = transparencygroups
-
-table.setmetatableindex(transparencygroups, function(transparencygroups,colormodel)
- local cs = colorspaceconstants[colormodel]
- if cs then
- local d = pdfdictionary {
- S = c_transparency,
- CS = cs,
- I = true,
- }
- -- local g = pdfreference(pdfflushobject(tostring(d)))
- local g = pdfreference(pdfdelayedobject(tostring(d)))
- transparencygroups[colormodel] = g
- return g
- else
- transparencygroups[colormodel] = false
- return false
- end
-end)
-
-local function addpagegroup()
- local model = getpagecolormodel()
- if model then
- local g = transparencygroups[model]
- if g then
- addtopageattributes("Group",g)
- end
- end
-end
-
-lpdf.registerpagefinalizer(addpagegroup,3,"pagegroup")
-
--- injection code (needs a bit reordering)
-
--- color injection
-
-function nodeinjections.rgbcolor(r,g,b)
- return register(pdfliteral(f_rgb(r,g,b,r,g,b)))
-end
-
-function nodeinjections.cmykcolor(c,m,y,k)
- return register(pdfliteral(f_cmyk(c,m,y,k,c,m,y,k)))
-end
-
-function nodeinjections.graycolor(s) -- caching 0/1 does not pay off
- return register(pdfliteral(f_gray(s,s)))
-end
-
-function nodeinjections.spotcolor(n,f,d,p)
- if type(p) == "string" then
- p = gsub(p,","," ") -- brr misuse of spot
- end
- return register(pdfliteral(f_spot(n,n,p,p)))
-end
-
-function nodeinjections.transparency(n)
- return register(pdfliteral(f_tr_gs(n)))
-end
-
--- a bit weird but let's keep it here for a while
-
-local effects = {
- normal = 0,
- inner = 0,
- outer = 1,
- both = 2,
- hidden = 3,
-}
-
-local bp = number.dimenfactors.bp
-
-function nodeinjections.effect(effect,stretch,rulethickness)
- -- always, no zero test (removed)
- rulethickness = bp * rulethickness
- effect = effects[effect] or effects['normal']
- return register(pdfliteral(f_effect(stretch,rulethickness,effect))) -- watch order
-end
-
--- spot- and indexcolors
-
-local pdf_separation = pdfconstant("Separation")
-local pdf_indexed = pdfconstant("Indexed")
-local pdf_device_n = pdfconstant("DeviceN")
-local pdf_device_rgb = pdfconstant("DeviceRGB")
-local pdf_device_cmyk = pdfconstant("DeviceCMYK")
-local pdf_device_gray = pdfconstant("DeviceGray")
-local pdf_extgstate = pdfconstant("ExtGState")
-
-local pdf_rbg_range = pdfarray { 0, 1, 0, 1, 0, 1 }
-local pdf_cmyk_range = pdfarray { 0, 1, 0, 1, 0, 1, 0, 1 }
-local pdf_gray_range = pdfarray { 0, 1 }
-
-local f_rgb_function = formatters["dup %s mul exch dup %s mul exch %s mul"]
-local f_cmyk_function = formatters["dup %s mul exch dup %s mul exch dup %s mul exch %s mul"]
-local f_gray_function = formatters["%s mul"]
-
-local documentcolorspaces = pdfdictionary()
-
-local spotcolorhash = { } -- not needed
-local spotcolornames = { }
-local indexcolorhash = { }
-local delayedindexcolors = { }
-
-function registrations.spotcolorname(name,e)
- spotcolornames[name] = e or name
-end
-
-function registrations.getspotcolorreference(name)
- return spotcolorhash[name]
-end
-
--- beware: xpdf/okular/evince cannot handle the spot->process shade
-
--- This should become delayed i.e. only flush when used; in that case we need
--- need to store the specification and then flush them when accesssomespotcolor
--- is called. At this moment we assume that splotcolors that get defined are
--- also used which keeps the overhad small anyway. Tricky for mp ...
-
-local processcolors
-
-local function registersomespotcolor(name,noffractions,names,p,colorspace,range,funct)
- noffractions = tonumber(noffractions) or 1 -- to be checked
- if noffractions == 0 then
- -- can't happen
- elseif noffractions == 1 then
- local dictionary = pdfdictionary {
- FunctionType = 4,
- Domain = { 0, 1 },
- Range = range,
- }
- local calculations = pdfflushstreamobject(format("{ %s }",funct),dictionary)
- -- local calculations = pdfobject {
- -- type = "stream",
- -- immediate = true,
- -- string = format("{ %s }",funct),
- -- attr = dictionary(),
- -- }
- local array = pdfarray {
- pdf_separation,
- pdfconstant(spotcolornames[name] or name),
- colorspace,
- pdfreference(calculations),
- }
- local m = pdfflushobject(array)
- local mr = pdfreference(m)
- spotcolorhash[name] = m
- documentcolorspaces[name] = mr
- adddocumentcolorspace(name,mr)
- else
- local cnames = pdfarray()
- local domain = pdfarray()
- local colorants = pdfdictionary()
- for n in gmatch(names,"[^,]+") do
- local name = spotcolornames[n] or n
- -- the cmyk names assume that they are indeed these colors
- if n == "cyan" then
- name = "Cyan"
- elseif n == "magenta" then
- name = "Magenta"
- elseif n == "yellow" then
- name = "Yellow"
- elseif n == "black" then
- name = "Black"
- else
- local sn = spotcolorhash[name] or spotcolorhash[n]
- if not sn then
- report_color("defining %a as colorant",name)
- colors.definespotcolor("",name,"p=1",true)
- sn = spotcolorhash[name] or spotcolorhash[n]
- end
- if sn then
- colorants[name] = pdfreference(sn)
- else
- -- maybe some day generate colorants (spot colors for multi) automatically
- report_color("unknown colorant %a, using black instead",name or n)
- name = "Black"
- end
- end
- cnames[#cnames+1] = pdfconstant(name)
- domain[#domain+1] = 0
- domain[#domain+1] = 1
- end
- if not processcolors then
- local specification = pdfdictionary {
- ColorSpace = pdfconstant("DeviceCMYK"),
- Components = pdfarray {
- pdfconstant("Cyan"),
- pdfconstant("Magenta"),
- pdfconstant("Yellow"),
- pdfconstant("Black")
- }
- }
- processcolors = pdfreference(pdfflushobject(specification))
- end
- local dictionary = pdfdictionary {
- FunctionType = 4,
- Domain = domain,
- Range = range,
- }
- local calculation = pdfflushstreamobject(format("{ %s %s }",rep("pop ",noffractions),funct),dictionary)
- local channels = pdfdictionary {
- Subtype = pdfconstant("NChannel"),
- Colorants = colorants,
- Process = processcolors,
- }
- local array = pdfarray {
- pdf_device_n,
- cnames,
- colorspace,
- pdfreference(calculation),
- pdfshareobjectreference(tostring(channels)), -- optional but needed for shades
- }
- local m = pdfflushobject(array)
- local mr = pdfreference(m)
- spotcolorhash[name] = m
- documentcolorspaces[name] = mr
- adddocumentcolorspace(name,mr)
- end
-end
-
--- wrong name
-
-local function registersomeindexcolor(name,noffractions,names,p,colorspace,range,funct)
- noffractions = tonumber(noffractions) or 1 -- to be checked
- local cnames = pdfarray()
- local domain = pdfarray()
- if names == "" then
- names = name .. ",None"
- else
- names = names .. ",None"
- end
- for n in gmatch(names,"[^,]+") do
- cnames[#cnames+1] = pdfconstant(spotcolornames[n] or n)
- domain[#domain+1] = 0
- domain[#domain+1] = 1
- end
- local dictionary = pdfdictionary {
- FunctionType = 4,
- Domain = domain,
- Range = range,
- }
- local n = pdfflushstreamobject(format("{ %s %s }",rep("exch pop ",noffractions),funct),dictionary) -- exch pop
- local a = pdfarray {
- pdf_device_n,
- cnames,
- colorspace,
- pdfreference(n),
- }
- if p == "" then
- p = "1"
- else
- p = p .. ",1"
- end
- local pi = { }
- for pp in gmatch(p,"[^,]+") do
- pi[#pi+1] = tonumber(pp)
- end
- local vector, set, n = { }, { }, #pi
- for i=255,0,-1 do
- for j=1,n do
- set[j] = format("%02X",round(pi[j]*i))
- end
- vector[#vector+1] = concat(set)
- end
- vector = pdfverbose { "<", concat(vector, " "), ">" }
- local n = pdfflushobject(pdfarray{ pdf_indexed, a, 255, vector })
- adddocumentcolorspace(format("%s_indexed",name),pdfreference(n))
- return n
-end
-
--- actually, names (parent) is the hash
-
-local function delayindexcolor(name,names,func)
- local hash = (names ~= "" and names) or name
- delayedindexcolors[hash] = func
-end
-
-local function indexcolorref(name) -- actually, names (parent) is the hash
- if not indexcolorhash[name] then
- local delayedindexcolor = delayedindexcolors[name]
- if type(delayedindexcolor) == "function" then
- indexcolorhash[name] = delayedindexcolor()
- delayedindexcolors[name] = true
- end
- end
- return indexcolorhash[name]
-end
-
-function registrations.rgbspotcolor(name,noffractions,names,p,r,g,b)
- if noffractions == 1 then
- registersomespotcolor(name,noffractions,names,p,pdf_device_rgb,pdf_rbg_range,f_rgb_function(r,g,b))
- else
- registersomespotcolor(name,noffractions,names,p,pdf_device_rgb,pdf_rbg_range,f_num_3(r,g,b))
- end
- delayindexcolor(name,names,function()
- return registersomeindexcolor(name,noffractions,names,p,pdf_device_rgb,pdf_rgb_range,f_rgb_function(r,g,b))
- end)
-end
-
-function registrations.cmykspotcolor(name,noffractions,names,p,c,m,y,k)
- if noffractions == 1 then
- registersomespotcolor(name,noffractions,names,p,pdf_device_cmyk,pdf_cmyk_range,f_cmyk_function(c,m,y,k))
- else
- registersomespotcolor(name,noffractions,names,p,pdf_device_cmyk,pdf_cmyk_range,f_num_4(c,m,y,k))
- end
- delayindexcolor(name,names,function()
- return registersomeindexcolor(name,noffractions,names,p,pdf_device_cmyk,pdf_cmyk_range,f_cmyk_function(c,m,y,k))
- end)
-end
-
-function registrations.grayspotcolor(name,noffractions,names,p,s)
- if noffractions == 1 then
- registersomespotcolor(name,noffractions,names,p,pdf_device_gray,pdf_gray_range,f_gray_function(s))
- else
- registersomespotcolor(name,noffractions,names,p,pdf_device_gray,pdf_gray_range,f_num_1(s))
- end
- delayindexcolor(name,names,function()
- return registersomeindexcolor(name,noffractions,names,p,pdf_device_gray,pdf_gray_range,f_gray_function(s))
- end)
-end
-
-function registrations.rgbindexcolor(name,noffractions,names,p,r,g,b)
- registersomeindexcolor(name,noffractions,names,p,pdf_device_rgb,pdf_rgb_range,f_rgb_function(r,g,b))
-end
-
-function registrations.cmykindexcolor(name,noffractions,names,p,c,m,y,k)
- registersomeindexcolor(name,noffractions,names,p,pdf_device_cmyk,pdf_cmyk_range,f_cmyk_function(c,m,y,k))
-end
-
-function registrations.grayindexcolor(name,noffractions,names,p,s)
- registersomeindexcolor(name,noffractions,names,p,pdf_device_gray,pdf_gray_range,f_gray_function(s))
-end
-
-function codeinjections.setfigurecolorspace(data,figure)
- local color = data.request.color
- if color then
- local ref = indexcolorref(color)
- if ref then
- figure.colorspace = ref
- data.used.color = color
- end
- end
-end
-
--- transparency
-
-local transparencies = { [0] =
- pdfconstant("Normal"),
- pdfconstant("Normal"),
- pdfconstant("Multiply"),
- pdfconstant("Screen"),
- pdfconstant("Overlay"),
- pdfconstant("SoftLight"),
- pdfconstant("HardLight"),
- pdfconstant("ColorDodge"),
- pdfconstant("ColorBurn"),
- pdfconstant("Darken"),
- pdfconstant("Lighten"),
- pdfconstant("Difference"),
- pdfconstant("Exclusion"),
- pdfconstant("Hue"),
- pdfconstant("Saturation"),
- pdfconstant("Color"),
- pdfconstant("Luminosity"),
- pdfconstant("Compatible"), -- obsolete; 'Normal' is used in this case
-}
-
-local documenttransparencies = { }
-local transparencyhash = { } -- share objects
-
-local done, signaled = false, false
-
-function registrations.transparency(n,a,t)
- if not done then
- local d = pdfdictionary {
- Type = pdf_extgstate,
- ca = 1,
- CA = 1,
- BM = transparencies[1],
- AIS = false,
- }
- local m = pdfflushobject(d)
- local mr = pdfreference(m)
- transparencyhash[0] = m
- documenttransparencies[0] = mr
- adddocumentextgstate("Tr0",mr)
- done = true
- end
- if n > 0 and not transparencyhash[n] then
- local d = pdfdictionary {
- Type = pdf_extgstate,
- ca = tonumber(t),
- CA = tonumber(t),
- BM = transparencies[tonumber(a)] or transparencies[0],
- AIS = false,
- }
- local m = pdfflushobject(d)
- local mr = pdfreference(m)
- transparencyhash[n] = m
- documenttransparencies[n] = mr
- adddocumentextgstate(f_tr(n),mr)
- end
-end
-
-statistics.register("page group warning", function()
- if done then
- local model = getpagecolormodel()
- if model and not transparencygroups[model] then
- return "transparencies are used but no pagecolormodel is set"
- end
- end
-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.
---
--- This module assumes that some functions are defined in the colors namespace
--- which most likely will be loaded later.
-
-local function lpdfcolor(model,ca,default) -- todo: use gray when no color
- if colors.supported then
- local cv = colorsvalue(ca)
- if cv then
- if model == 1 then
- model = cv[1]
- end
- model = forcedmodel(model)
- if model == 2 then
- local s = cv[2]
- return f_gray(s,s)
- elseif model == 3 then
- local r, g, b = cv[3], cv[4], cv[5]
- return f_rgb(r,g,b,r,g,b)
- elseif model == 4 then
- local c, m, y, k = cv[6],cv[7],cv[8],cv[9]
- return f_cmyk(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 = gsub(p,","," ") -- brr misuse of spot
- end
- return f_spot(n,n,p,p)
- end
- else
- return f_gray(default or 0,default or 0)
- end
- else
- return ""
- end
-end
-
-lpdf.color = lpdfcolor
-
-interfaces.implement {
- name = "lpdf_color",
- actions = { lpdfcolor, context },
- arguments = "integer"
-}
-
-function lpdf.colorspec(model,ca,default)
- if ca and ca > 0 then
- local cv = colors.value(ca)
- if cv then
- if model == 1 then
- model = cv[1]
- end
- if model == 2 then
- return pdfarray { cv[2] }
- elseif model == 3 then
- return pdfarray { cv[3],cv[4],cv[5] }
- elseif model == 4 then
- return pdfarray { cv[6],cv[7],cv[8],cv[9] }
- elseif model == 5 then
- return pdfarray { cv[13] }
- end
- end
- end
- if default then
- return default
- end
-end
-
-function lpdf.pdfcolor(attribute) -- bonus, for pgf and friends
- return lpdfcolor(1,attribute)
-end
-
-function lpdf.transparency(ct,default) -- kind of overlaps with transparencycode
- -- beware, we need this hack because normally transparencies are not
- -- yet registered and therefore the number is not not known ... we
- -- might use the attribute number itself in the future
- if transparencies.supported then
- local ct = transparenciesvalue(ct)
- if ct then
- return f_tr_gs(registertransparancy(nil,ct[1],ct[2],true))
- else
- return f_tr_gs(0)
- end
- else
- return ""
- end
-end
-
-function lpdf.colorvalue(model,ca,default)
- local cv = colorsvalue(ca)
- if cv then
- if model == 1 then
- model = cv[1]
- end
- model = forcedmodel(model)
- if model == 2 then
- return f_num_1(cv[2])
- elseif model == 3 then
- return f_num_3(cv[3],cv[4],cv[5])
- elseif model == 4 then
- return f_num_4(cv[6],cv[7],cv[8],cv[9])
- else
- return f_num_1(cv[13])
- end
- else
- return f_num_1(default or 0)
- end
-end
-
-function lpdf.colorvalues(model,ca,default)
- local cv = colorsvalue(ca)
- if cv then
- if model == 1 then
- model = cv[1]
- end
- model = forcedmodel(model)
- if model == 2 then
- return cv[2]
- elseif model == 3 then
- return cv[3], cv[4], cv[5]
- elseif model == 4 then
- return cv[6], cv[7], cv[8], cv[9]
- elseif model == 4 then
- return cv[13]
- end
- else
- return default or 0
- end
-end
-
-function lpdf.transparencyvalue(ta,default)
- local tv = transparenciesvalue(ta)
- if tv then
- return tv[2]
- else
- return default or 1
- end
-end
-
-function lpdf.colorspace(model,ca)
- local cv = colorsvalue(ca)
- if cv then
- if model == 1 then
- model = cv[1]
- end
- model = forcedmodel(model)
- if model == 2 then
- return "DeviceGray"
- elseif model == 3 then
- return "DeviceRGB"
- elseif model == 4 then
- return "DeviceCMYK"
- end
- end
- return "DeviceGRAY"
-end
-
--- by registering we getconversion for free (ok, at the cost of overhead)
-
-local intransparency = false
-local pdfcolor = lpdf.color
-
-function lpdf.rgbcode(model,r,g,b)
- if colors.supported then
- return pdfcolor(model,registercolor(nil,'rgb',r,g,b))
- else
- return ""
- end
-end
-
-function lpdf.cmykcode(model,c,m,y,k)
- if colors.supported then
- return pdfcolor(model,registercolor(nil,'cmyk',c,m,y,k))
- else
- return ""
- end
-end
-
-function lpdf.graycode(model,s)
- if colors.supported then
- return pdfcolor(model,registercolor(nil,'gray',s))
- else
- return ""
- end
-end
-
-function lpdf.spotcode(model,n,f,d,p)
- if colors.supported then
- return pdfcolor(model,registercolor(nil,'spot',n,f,d,p)) -- incorrect
- else
- return ""
- end
-end
-
-function lpdf.transparencycode(a,t)
- if transparencies.supported then
- intransparency = true
- return f_tr_gs(registertransparancy(nil,a,t,true)) -- true forces resource
- else
- return ""
- end
-end
-
-function lpdf.finishtransparencycode()
- if transparencies.supported and intransparency then
- intransparency = false
- return f_tr_gs(0) -- we happen to know this -)
- else
- return ""
- end
-end
-
--- this will move to lpdf-spe.lua
-
-local f_slant = formatters["pdf: q 1 0 %F 1 0 0 cm"]
-
-backends.pdf.tables.vfspecials = allocate { -- todo: distinguish between glyph and rule color
-
- red = { "special", 'pdf: 1 0 0 rg 1 0 0 RG' },
- green = { "special", 'pdf: 0 1 0 rg 0 1 0 RG' },
- blue = { "special", 'pdf: 0 0 1 rg 0 0 1 RG' },
- gray = { "special", 'pdf: .75 g .75 G' },
- black = { "special", 'pdf: 0 g 0 G' },
-
- rulecolors = {
- red = { "special", 'pdf: 1 0 0 rg' },
- green = { "special", 'pdf: 0 1 0 rg' },
- blue = { "special", 'pdf: 0 0 1 rg' },
- gray = { "special", 'pdf: .5 g' },
- black = { "special", 'pdf: 0 g' },
- palered = { "special", 'pdf: 1 .75 .75 rg' },
- palegreen = { "special", 'pdf: .75 1 .75 rg' },
- paleblue = { "special", 'pdf: .75 .75 1 rg' },
- palegray = { "special", 'pdf: .75 g' },
- },
-
- startslant = function(a) return { "special", f_slant(a) } end,
- stopslant = { "special", "pdf: Q" },
-
-}