diff options
author | Taco Hoekwater <taco@elvenkind.com> | 2008-06-12 10:42:53 +0000 |
---|---|---|
committer | Taco Hoekwater <taco@elvenkind.com> | 2008-06-12 10:42:53 +0000 |
commit | 0d01365d53c456d246da0ca1f0b3cd9868f02b35 (patch) | |
tree | 01a655c8028e17cfb371456b299c1848fe08c05b /Master/texmf-dist/tex/context/base/mlib-pps.lua | |
parent | 44f3714442da07fdfc36a7f2a8dcd5d4294c5d26 (diff) |
ConTeXt release 2008.05.21
git-svn-id: svn://tug.org/texlive/trunk@8691 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/context/base/mlib-pps.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/mlib-pps.lua | 832 |
1 files changed, 832 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/context/base/mlib-pps.lua b/Master/texmf-dist/tex/context/base/mlib-pps.lua new file mode 100644 index 00000000000..0e3d2e3ecea --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mlib-pps.lua @@ -0,0 +1,832 @@ +if not modules then modules = { } end modules ['mlib-pps'] = { -- prescript, postscripts and specials + version = 1.001, + comment = "companion to mlib-ctx.tex", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files", +} + +local format, concat, round = string.format, table.concat, math.round +local sprint = tex.sprint + +colors = colors or { } + +local rgbtocmyk = colors.rgbtocmyk or function() return 0,0,0,1 end +local cmyktorgb = colors.cmyktorgb or function() return 0,0,0 end +local rgbtogray = colors.rgbtogray or function() return 0 end +local cmyktogray = colors.cmyktogray or function() return 0 end + +metapost = metapost or { } +metapost.specials = metapost.specials or { } +metapost.specials.data = metapost.specials.data or { } + +local data = metapost.specials.data + +local colordata = { {}, {}, {}, {}, {} } + +--~ (r,g,b) => cmyk : r=123 g= 1 b=hash +--~ => spot : r=123 g= 2 b=hash +--~ => transparent rgb : r=123 g= 3 b=hash +--~ => transparent cmyk : r=123 g= 4 b=hash +--~ => transparent spot : r=123 g= 5 b=hash +--~ => rest : r=123 g=n>10 b=whatever + +function metapost.specials.register(str) -- only colors + local size, content, n, class = str:match("^%%%%MetaPostSpecial: (%d+) (.*) (%d+) (%d+)$") + if class then + local data = { } + for s in content:gmatch("[^ ]+") do + data[#data+1] = s + end + class, n = tonumber(class), tonumber(n) + if class == 3 or class == 4 or class == 5 then -- weird + colordata[class][n] = data + else + colordata[class][tonumber(data[1])] = data + end + end +end + +function metapost.colorhandler(cs, object, result, colorconverter) + local cr = "0 g 0 G" + local what = round(cs[2]*10000) + local data = colordata[what][round(cs[3]*10000)] + if not data then + -- + elseif what == 1 then + result[#result+1], cr = colorconverter({ data[2], data[3], data[4], data[5] }) + elseif what == 2 then + ctx.registerspotcolor(data[2]) + result[#result+1] = ctx.pdfcolor(colors.model,colors.register('color',nil,'spot',data[2],data[3],data[4],data[5])) + else + if what == 3 then + result[#result+1], cr = colorconverter({ data[3], data[4], data[5]}) + elseif what == 4 then + result[#result+1], cr = colorconverter({ data[3], data[4], data[5], data[6]}) + elseif what == 5 then + ctx.registerspotcolor(data[3]) + result[#result+1] = ctx.pdfcolor(colors.model,colors.register('color',nil,'spot',data[3],data[4],data[5],data[6])) + end + object.prescript = "tr" + object.postscript = data[1] .. "," .. data[2] + end + object.color = nil + return object, cr +end + +function metapost.colorspec(cs) + local what = round(cs[2]*10000) + local data = colordata[what][round(cs[3]*10000)] + if not data then + return { 0 } + elseif what == 1 then + return { data[2], data[3], data[4], data[5] } + elseif what == 2 then + ctx.registerspotcolor(data[2]) + return ctx.pdfcolor(colors.model,colors.register('color',nil,'spot',data[2],data[3],data[4],data[5])) + elseif what == 3 then + return { data[3], data[4], data[5] } + elseif what == 4 then + return { data[3], data[4], data[5], data[6] } + elseif what == 5 then + ctx.registerspotcolor(data[3]) + return ctx.pdfcolor(colors.model,colors.register('color',nil,'spot',data[3],data[4],data[5],data[6])) + end +end + +function metapost.specials.tr(specification,object,result) + local a, t = specification:match("^(.+),(.+)$") + local before = a and t and function() + result[#result+1] = format("/Tr%s gs",transparencies.register('mp',a,t)) + return object, result + end + local after = before and function() + result[#result+1] = "/Tr0 gs" + return object, result + end + return object, before, nil, after +end + +--~ -- possible speedup: hash registered colors +--~ +--~ function metapost.specials.sp(specification,object,result) -- todo: color conversion +--~ local s = object.color[1] +--~ object.color = nil +--~ local before = function() +--~ local spec = specification:split(" ") +--~ ctx.registerspotcolor(spec[1]) +--~ result[#result+1] = ctx.pdfcolor(colors.model,colors.register('color',nil,'spot',spec[1],spec[2],spec[3],s)) +--~ return object, result +--~ end +--~ local after = function() +--~ result[#result+1] = "0 g 0 G" +--~ return object, result +--~ end +--~ return object, before, nil, nil +--~ end + +-- Unfortunately we cannot use cmyk colors natively because there is no +-- generic color allocation primitive ... it's just an rgbcolor color.. This +-- means that we cannot pass colors in either cmyk or rgb form. +-- +-- def cmyk(expr c,m,y,k) = +-- 1 withprescript "cc" withpostscript ddddecimal (c,m,y,k) +-- enddef ; +-- +-- This is also an example of a simple plugin. + +--~ function metapost.specials.cc(specification,object,result) +--~ object.color = specification:split(" ") +--~ return object, nil, nil, nil +--~ end +--~ function metapost.specials.cc(specification,object,result) +--~ local c = specification:split(" ") +--~ local o = object.color[1] +--~ c[1],c[2],c[3],c[4] = o*c[1],o*c[2],o*c[3],o*c[4] +--~ return object, nil, nil, nil +--~ end + +-- thanks to taco's reading of the postscript manual: +-- +-- x' = sx * x + ry * y + tx +-- y' = rx * x + sy * y + ty + +function metapost.specials.fg(specification,object,result,flusher) + local op = object.path + local first, second, fourth = op[1], op[2], op[4] + local tx, ty = first.x_coord , first.y_coord + local sx, sy = second.x_coord - tx, fourth.y_coord - ty + local rx, ry = second.y_coord - ty, fourth.x_coord - tx + if sx == 0 then sx = 0.00001 end + if sy == 0 then sy = 0.00001 end + local before = specification and function() + flusher.flushfigure(result) + sprint(tex.ctxcatcodes,format("\\MPLIBfigure{%f}{%f}{%f}{%f}{%f}{%f}{%s}",sx,rx,ry,sy,tx,ty,specification)) + return object, { } + end + return { } , before, nil, nil -- replace { } by object for tracing +end + +local nofshades = 0 -- todo: hash resources, start at 1000 in order not to clash with older + +local function normalize(ca,cb) + if #cb == 1 then + if #ca == 4 then + cb[1], cb[2], cb[3], cb[4] = 0, 0, 0, 1-cb[1] + else + cb[1], cb[2], cb[3] = cb[1], cb[1], cb[1] + end + elseif #cb == 3 then + if #ca == 4 then + cb[1], cb[2], cb[3], cb[4] = rgbtocmyk(cb[1],cb[2],cb[3]) + else + cb[1], cb[2], cb[3] = cmyktorgb(cb[1],cb[2],cb[3],cb[4]) + end + end +end + +function metapost.specials.cs(specification,object,result,flusher) -- spot colors? + nofshades = nofshades + 1 + flusher.flushfigure(result) + result = { } + local t = specification:split(" ") + -- we need a way to move/scale + local ca = t[4]:split(":") + local cb = t[8]:split(":") + if round(ca[1]*10000) == 123 then ca = metapost.colorspec(ca) end + if round(cb[1]*10000) == 123 then cb = metapost.colorspec(cb) end + if type(ca) == "string" then + -- spot color, not supported, maybe at some point use the fallbacks + sprint(tex.ctxcatcodes,format("\\MPLIBcircularshade{%s}{%s %s}{%.3f}{%.3f}{%s}{%s}{%s %s %s %s %s %s}", + nofshades, + t[1], t[2], 0, 1, 1, "DeviceGray", + t[5], t[6], t[7], t[9], t[10], t[11])) + else + if #ca > #cb then + normalize(ca,cb) + elseif #ca < #cb then + normalize(cb,ca) + end + local model = colors.model + if model == "all" then + model= (#ca == 4 and "cmyk") or (#ca == 3 and "rgb") or "gray" + end + if model == "rgb" then + if #ca == 4 then + ca[1], ca[2], ca[3] = cmyktorgb(ca[1],ca[2],ca[3],ca[4]) + cb[1], cb[2], cb[3] = cmyktorgb(cb[1],cb[2],cb[3],cb[4]) + elseif #ca == 1 then + local a, b = 1-ca[1], 1-cb[1] + ca[1], ca[2], ca[3] = a, a, a + cb[1], cb[2], cb[3] = b, b, b + end + sprint(tex.ctxcatcodes,format("\\MPLIBcircularshade{%s}{%s %s}{%.3f %.3f %.3f}{%.3f %.3f %.3f}{%s}{%s}{%s %s %s %s %s %s}", + nofshades, + t[1], t[2], ca[1], ca[2], ca[3], cb[1], cb[2], cb[3], 1, "DeviceRGB", + t[5], t[6], t[7], t[9], t[10], t[11])) + elseif model == "cmyk" then + if #ca == 3 then + ca[1], ca[2], ca[3], ca[4] = rgbtocmyk(ca[1],ca[2],ca[3]) + cb[1], cb[2], cb[3], ca[4] = rgbtocmyk(cb[1],cb[2],cb[3]) + elseif #ca == 1 then + ca[1], ca[2], ca[3], ca[4] = 0, 0, 0, ca[1] + cb[1], cb[2], cb[3], ca[4] = 0, 0, 0, ca[1] + end + sprint(tex.ctxcatcodes,format("\\MPLIBcircularshade{%s}{%s %s}{%.3f %.3f %.3f %.3f}{%.3f %.3f %.3f %.3f}{%s}{%s}{%s %s %s %s %s %s}", + nofshades, + t[1], t[2], ca[1], ca[2], ca[3], ca[4], cb[1], cb[2], cb[3], cb[4], 1, "DeviceCMYK", + t[5], t[6], t[7], t[9], t[10], t[11])) + else + if #ca == 4 then + ca[1] = cmyktogray(ca[1],ca[2],ca[3],ca[4]) + cb[1] = cmyktogray(cb[1],cb[2],cb[3],cb[4]) + elseif #ca == 3 then + ca[1] = rgbtogray(ca[1],ca[2],ca[3]) + cb[1] = rgbtogray(cb[1],cb[2],cb[3]) + end + sprint(tex.ctxcatcodes,format("\\MPLIBcircularshade{%s}{%s %s}{%.3f}{%.3f}{%s}{%s}{%s %s %s %s %s %s}", + nofshades, + t[1], t[2], ca[1], cb[1], 1, "DeviceGray", + t[5], t[6], t[7], t[9], t[10], t[11])) + end + end + local before = function() + result[#result+1] = "q /Pattern cs" + return object, result + end + local after = function() + result[#result+1] = format("W n /MpSh%s sh Q", nofshades) + return object, result + end + object.color, object.type = nil, nil + return object, before, nil, after +end + +function metapost.specials.ls(specification,object,result,flusher) + nofshades = nofshades + 1 + flusher.flushfigure(result) + result = { } + local t = specification:split(" ") + -- we need a way to move/scale + local ca = t[4]:split(":") + local cb = t[7]:split(":") + if round(ca[1]*10000) == 123 then ca = metapost.colorspec(ca) end + if round(cb[1]*10000) == 123 then cb = metapost.colorspec(cb) end + if type(ca) == "string" then + -- spot color, not supported, maybe at some point use the fallbacks + sprint(tex.ctxcatcodes,format("\\MPLIBlinearshade{%s}{%s %s}{%.3f}{%.3f}{%s}{%s}{%s %s %s %s}", + nofshades, + t[1], t[2], 0, 1, 1, "DeviceGray", + t[5], t[6], t[8], t[9])) + else + if #ca > #cb then + normalize(ca,cb) + elseif #ca < #cb then + normalize(cb,ca) + end + local model = colors.model + if model == "all" then + model= (#ca == 4 and "cmyk") or (#ca == 3 and "rgb") or "gray" + end + if model == "rgb" then + if #ca == 4 then + ca[1], ca[2], ca[3] = cmyktorgb(ca[1],ca[2],ca[3],ca[4]) + cb[1], cb[2], cb[3] = cmyktorgb(cb[1],cb[2],cb[3],cb[4]) + elseif #ca == 1 then + local a, b = 1-ca[1], 1-cb[1] + ca[1], ca[2], ca[3] = a, a, a + cb[1], cb[2], cb[3] = b, b, b + end + sprint(tex.ctxcatcodes,format("\\MPLIBlinearshade{%s}{%s %s}{%.3f %.3f %.3f}{%.3f %.3f %.3f}{%s}{%s}{%s %s %s %s}", + nofshades, + t[1], t[2], ca[1], ca[2], ca[3], cb[1], cb[2], cb[3], 1, "DeviceRGB", + t[5], t[6], t[8], t[9])) + elseif model == "cmyk" then + if #ca == 3 then + ca[1], ca[2], ca[3], ca[4] = rgbtocmyk(ca[1],ca[2],ca[3]) + cb[1], cb[2], cb[3], ca[4] = rgbtocmyk(cb[1],cb[2],cb[3]) + elseif #ca == 1 then + ca[1], ca[2], ca[3], ca[4] = 0, 0, 0, ca[1] + cb[1], cb[2], cb[3], ca[4] = 0, 0, 0, ca[1] + end + sprint(tex.ctxcatcodes,format("\\MPLIBlinearshade{%s}{%s %s}{%.3f %.3f %.3f %.3f}{%.3f %.3f %.3f %.3f}{%s}{%s}{%s %s %s %s}", + nofshades, + t[1], t[2], ca[1], ca[2], ca[3], ca[4], cb[1], cb[2], cb[3], cb[4], 1, "DeviceCMYK", + t[5], t[6], t[8], t[9])) + else + if #ca == 4 then + ca[1] = cmyktogray(ca[1],ca[2],ca[3],ca[4]) + cb[1] = cmyktogray(cb[1],cb[2],cb[3],cb[4]) + elseif #ca == 3 then + ca[1] = rgbtogray(ca[1],ca[2],ca[3]) + cb[1] = rgbtogray(cb[1],cb[2],cb[3]) + end + sprint(tex.ctxcatcodes,format("\\MPLIBlinearshade{%s}{%s %s}{%.3f}{%.3f}{%s}{%s}{%s %s %s %s}", + nofshades, + t[1], t[2], ca[1], cb[1], 1, "DeviceGray", + t[5], t[6], t[8], t[9])) + end + end + local before = function() + result[#result+1] = "q /Pattern cs" + return object, result + end + local after = function() + result[#result+1] = format("W n /MpSh%s sh Q", nofshades) + return object, result + end + object.color, object.type = nil, nil + return object, before, nil, after +end + +-- no need for a before here + +local current_format, current_graphic + +--~ metapost.first_box, metapost.last_box = 1000, 1100 + +metapost.textext_current = metapost.first_box +metapost.trace_texttexts = false +metapost.multipass = false + +function metapost.specials.tf(specification,object) +--~ print("setting", metapost.textext_current) + local n, str = specification:match("^(%d+):(.+)$") + if metapost.textext_current < metapost.last_box then + metapost.textext_current = metapost.first_box + n - 1 + end + if metapost.trace_texttexts then + print("metapost", format("first pass: order %s, box %s",n,metapost.textext_current)) + end + sprint(tex.ctxcatcodes,format("\\MPLIBsettext{%s}{%s}",metapost.textext_current,str)) + metapost.multipass = true + return { }, nil, nil, nil +end + +function metapost.specials.ts(specification,object,result,flusher) + -- print("getting", metapost.textext_current) + local n, str = specification:match("^(%d+):(.+)$") + if metapost.trace_texttexts then + print("metapost", format("second pass: order %s, box %s",n,metapost.textext_current)) + end + local op = object.path + local first, second, fourth = op[1], op[2], op[4] + local tx, ty = first.x_coord , first.y_coord + local sx, sy = second.x_coord - tx, fourth.y_coord - ty + local rx, ry = second.y_coord - ty, fourth.x_coord - tx + if sx == 0 then sx = 0.00001 end + if sy == 0 then sy = 0.00001 end + local before = function() -- no need for function + --~ flusher.flushfigure(result) + --~ sprint(tex.ctxcatcodes,format("\\MPLIBgettext{%f}{%f}{%f}{%f}{%f}{%f}{%s}",sx,rx,ry,sy,tx,ty,metapost.textext_current)) + --~ result = { } + result[#result+1] = format("q %f %f %f %f %f %f cm", sx,rx,ry,sy,tx,ty) + flusher.flushfigure(result) + if metapost.textext_current < metapost.last_box then + metapost.textext_current = metapost.first_box + n - 1 + end + local b = metapost.textext_current + sprint(tex.ctxcatcodes,format("\\MPLIBgettextscaled{%s}{%s}{%s}",b, metapost.sxsy(tex.wd[b],tex.ht[b],tex.dp[b]))) + result = { "Q" } + return object, result + end + return { }, before, nil, nil -- replace { } by object for tracing +end + +function metapost.colorconverter() + -- it no longer pays off to distinguish between outline and fill + -- (we now have both too, e.g. in arrows) + local model = colors.model + if model == "all" then + return function(cr) + local n = #cr + if n == 1 then + local s = cr[1] + return format("%.3f g %.3f G",s,s), "0 g 0 G" + elseif n == 4 then + local c, m, y, k = cr[1], cr[2], cr[3], cr[4] + return format("%.3f %.3f %.3f %.3f k %.3f %.3f %.3f %.3f K",c,m,y,k,c,m,y,k), "0 g 0 G" + else + local r, g, b = cr[1], cr[2], cr[3] + return format("%.3f %.3f %.3f rg %.3f %.3f %.3f RG",r,g,b,r,g,b), "0 g 0 G" + end + end + elseif model == "rgb" then + return function(cr) + local n = #cr + if n == 1 then + local s = cr[1] + return format("%.3f g %.3f G",s,s), "0 g 0 G" + end + local r, g, b + if n == 4 then + r, g, b = cmyktorgb(cr[1],cr[2],cr[3],cr[4]) + else + r, g, b = cr[1],cr[2],cr[3] + end + return format("%.3f %.3f %.3f rg %.3f %.3f %.3f RG",r,g,b,r,g,b), "0 g 0 G" + end + elseif model == "cmyk" then + return function(cr) + local n = #cr + if n == 1 then + local s = cr[1] + return format("%.3f g %.3f G",s,s), "0 g 0 G" + end + local c, m, y, k + if n == 4 then + c, m, y, k = cr[1], cr[2], cr[3], cr[4] + else + c, m, y, k = rgbtocmyk(cr[1],cr[2],cr[3]) + end + return format("%.3f %.3f %.3f %.3f k %.3f %.3f %.3f %.3f K",c,m,y,k,c,m,y,k), "0 g 0 G" + end + else + return function(cr) + local s + local n = #cr + if n == 4 then + s = cmyktogray(cr[1],cr[2],cr[3],cr[4]) + elseif n == 3 then + s = rgbtogray(cr[1],cr[2],cr[3]) + else + s = cr[1] + end + return format("%.3f g %.3f G",s,s), "0 g 0 G" + end + end +end + +--~ local cmyk_fill = "%.3f %.3f %.3f %.3f k" +--~ local rgb_fill = "%.3f %.3f %.3f rg" +--~ local gray_fill = "%.3f g" +--~ local reset_fill = "0 g" + +--~ local cmyk_stroke = "%.3f %.3f %.3f %.3f K" +--~ local rgb_stroke = "%.3f %.3f %.3f RG" +--~ local gray_stroke = "%.3f G" +--~ local reset_stroke = "0 G" + +metapost.reducetogray = true + +function metapost.colorconverter() -- rather generic pdf, so use this elsewhere too + -- it no longer pays off to distinguish between outline and fill + -- (we now have both too, e.g. in arrows) + local model = colors.model + local reduce = metapost.reducetogray + if model == "all" then + return function(cr) + local n = #cr + if reduce then + if n == 1 then + local s = cr[1] + return format("%.3f g %.3f G",s,s), "0 g 0 G" + elseif n == 3 then + local r, g, b = cr[1], cr[2], cr[3] + if r == g and g == b then + return format("%.3f g %.3f G",r,r), "0 g 0 G" + else + return format("%.3f %.3f %.3f rg %.3f %.3f %.3f RG",r,g,b,r,g,b), "0 g 0 G" + end + else + local c, m, y, k = cr[1], cr[2], cr[3], cr[4] + if c == m and m == y and y == 0 then + k = 1 - k + return format("%.3f g %.3f G",k,k), "0 g 0 G" + else + return format("%.3f %.3f %.3f %.3f k %.3f %.3f %.3f %.3f K",c,m,y,k,c,m,y,k), "0 g 0 G" + end + end + elseif n == 1 then + local s = cr[1] + return format("%.3f g %.3f G",s,s), "0 g 0 G" + elseif n == 3 then + local r, g, b = cr[1], cr[2], cr[3] + return format("%.3f %.3f %.3f rg %.3f %.3f %.3f RG",r,g,b,r,g,b), "0 g 0 G" + else + local c, m, y, k = cr[1], cr[2], cr[3], cr[4] + return format("%.3f %.3f %.3f %.3f k %.3f %.3f %.3f %.3f K",c,m,y,k,c,m,y,k), "0 g 0 G" + end + end + elseif model == "rgb" then + return function(cr) + local n = #cr + if reduce then + if n == 1 then + local s = cr[1] + return format("%.3f g %.3f G",s,s), "0 g 0 G" + elseif n == 3 then + local r, g, b = cr[1], cr[2], cr[3] + if r == g and g == b then + return format("%.3f g %.3f G",r,r), "0 g 0 G" + else + return format("%.3f %.3f %.3f rg %.3f %.3f %.3f RG",r,g,b,r,g,b), "0 g 0 G" + end + else + local c, m, y, k = cr[1], cr[2], cr[3], cr[4] + if c == m and m == y and y == 0 then + k = 1 - k + return format("%.3f g %.3f G",k,k), "0 g 0 G" + else + local r, g, b = cmyktorgb(c,m,y,k) + return format("%.3f %.3f %.3f rg %.3f %.3f %.3f RG",r,g,b,r,g,b), "0 g 0 G" + end + end + elseif n == 1 then + local s = cr[1] + return format("%.3f g %.3f G",s,s), "0 g 0 G" + else + local r, g, b + if n == 3 then + r, g, b = cmyktorgb(cr[1],cr[2],cr[3],cr[4]) + else + r, g, b = cr[1], cr[2], cr[3] + end + return format("%.3f %.3f %.3f rg %.3f %.3f %.3f RG",r,g,b,r,g,b), "0 g 0 G" + end + end + elseif model == "cmyk" then + return function(cr) + local n = #cr + if reduce then + if n == 1 then + local s = cr[1] + return format("%.3f g %.3f G",s,s), "0 g 0 G" + elseif n == 3 then + local r, g, b = cr[1], cr[2], cr[3] + if r == g and g == b then + return format("%.3f g %.3f G",r,r), "0 g 0 G" + else + local c, m, y, k = rgbtocmyk(r,g,b) + return format("%.3f %.3f %.3f %.3f k %.3f %.3f %.3f %.3f K",c,m,y,k,c,m,y,k), "0 g 0 G" + end + else + local c, m, y, k = cr[1], cr[2], cr[3], cr[4] + if c == m and m == y and y == 0 then + k = 1 - k + return format("%.3f g %.3f G",k,k), "0 g 0 G" + else + return format("%.3f %.3f %.3f %.3f k %.3f %.3f %.3f %.3f K",c,m,y,k,c,m,y,k), "0 g 0 G" + end + end + elseif n == 1 then + local s = cr[1] + return format("%.3f g %.3f G",s,s), "0 g 0 G" + else + local c, m, y, k + if n == 3 then + c, m, y, k = rgbtocmyk(cr[1],cr[2],cr[3]) + else + c, m, y, k = cr[1], cr[2], cr[3], cr[4] + end + return format("%.3f %.3f %.3f %.3f k %.3f %.3f %.3f %.3f K",c,m,y,k,c,m,y,k), "0 g 0 G" + end + end + else + return function(cr) + local n, s = #cr, 0 + if n == 4 then + s = cmyktogray(cr[1],cr[2],cr[3],cr[4]) + elseif n == 3 then + s = rgbtogray(cr[1],cr[2],cr[3]) + else + s = cr[1] + end + return format("%.3f g %.3f G",s,s), "0 g 0 G" + end + end +end + +do + + local P, S, V, Cs = lpeg.P, lpeg.S, lpeg.V, lpeg.Cs + + local btex = P("btex") + local etex = P(" etex") + local vtex = P("verbatimtex") + local ttex = P("textext") + local gtex = P("graphictext") + local spacing = S(" \n\r\t\v")^0 + local dquote = P('"') + + local found = false + + local function convert(str) + found = true + return "textext(\"" .. str .. "\")" + end + local function ditto(str) + return "\" & ditto & \"" + end + local function register() + found = true + end + + local parser = P { + [1] = Cs((V(2)/register + V(3)/convert + 1)^0), + [2] = ttex + gtex, + [3] = (btex + vtex) * spacing * Cs((dquote/ditto + (1 - etex))^0) * etex, + } + + -- currently a a one-liner produces less code + + local parser = Cs(((ttex + gtex)/register + ((btex + vtex) * spacing * Cs((dquote/ditto + (1 - etex))^0) * etex)/convert + 1)^0) + + function metapost.check_texts(str) + found = false + return parser:match(str), found + end + +end + +local factor = 65536*(7200/7227) + +function metapost.edefsxsy(wd,ht,dp) -- helper for text + commands.edef("sx",(wd ~= 0 and 1/( wd /(factor))) or 0) + commands.edef("sy",(wd ~= 0 and 1/((ht+dp)/(factor))) or 0) +end + +function metapost.sxsy(wd,ht,dp) -- helper for text + return (wd ~= 0 and 1/(wd/(factor))) or 0, (wd ~= 0 and 1/((ht+dp)/(factor))) or 0 +end + +function metapost.text_texts_data() + local t, n = { }, 0 + for i = metapost.first_box, metapost.last_box do + n = n + 1 + if metapost.trace_texttexts then + print("metapost", format("passed data: order %s, box %s",n,i)) + end + if tex.box[i] then + t[#t+1] = format("_tt_w_[%i]:=%f;_tt_h_[%i]:=%f;_tt_d_[%i]:=%f;", n,tex.wd[i]/factor, n,tex.ht[i]/factor, n,tex.dp[i]/factor) + else + break + end + end + return t +end + +metapost.intermediate = metapost.intermediate or {} +metapost.intermediate.actions = metapost.intermediate.actions or {} +metapost.intermediate.needed = false + +--~ function metapost.graphic_base_pass(mpsformat,str,preamble) +--~ local prepared, done = metapost.check_texts(str) +--~ metapost.textext_current = metapost.first_box +--~ metapost.intermediate.needed = false +--~ if done then +--~ current_format, current_graphic = mpsformat, prepared +--~ metapost.process(mpsformat, { +--~ preamble or "", +--~ "beginfig(1); ", +--~ "_trial_run_ := true ;", +--~ prepared, +--~ "endfig ;" +--~ }, true ) -- true means: trialrun +--~ if metapost.intermediate.needed then +--~ for _, action in pairs(metapost.intermediate.actions) do +--~ action() +--~ end +--~ end +--~ sprint(tex.ctxcatcodes,"\\ctxlua{metapost.graphic_extra_pass()}") +--~ else +--~ metapost.process(mpsformat, { +--~ preamble or "", +--~ "beginfig(1); ", +--~ "_trial_run_ := false ;", +--~ "resettextexts;", +--~ str, +--~ "endfig ;" +--~ } ) +--~ end +--~ end + +metapost.method = 1 -- 1:dumb 2:clever + +function metapost.graphic_base_pass(mpsformat,str,preamble) + local done_1, done_2 + str, done_1 = metapost.check_texts(str) + if preamble then + preamble, done_2 = metapost.check_texts(preamble) + else + preamble, done_2 = "", false + end + metapost.textext_current = metapost.first_box + metapost.intermediate.needed = false + metapost.multipass = false -- no needed here + current_format, current_graphic = mpsformat, str + if metapost.method == 1 or (metapost.method == 2 and (done_1 or done_2)) then + local flushed = metapost.process(mpsformat, { + preamble, + "beginfig(1); ", + "_trial_run_ := true ;", +--~ "resettextexts;", + str, + "endfig ;" + }, true, nil, true ) -- true means: trialrun, true means: avoid extra run if no multipass + if metapost.intermediate.needed then + for _, action in pairs(metapost.intermediate.actions) do + action() + end + end + if not flushed then + sprint(tex.ctxcatcodes,"\\ctxlua{metapost.graphic_extra_pass()}") + end + else + metapost.process(mpsformat, { + preamble or "", + "beginfig(1); ", + "_trial_run_ := false ;", +--~ "resettextexts;", + str, + "endfig ;" + } ) + end +end + +function metapost.graphic_extra_pass() + metapost.textext_current = metapost.first_box + metapost.process(current_format, { + "beginfig(0); ", + "_trial_run_ := false ;", +--~ "resettextexts;", + concat(metapost.text_texts_data()," ;\n"), + current_graphic, + "endfig ;" + }) +end + +function metapost.getclippath(data) + local mpx = metapost.format("metafun") + if mpx and data then + input.starttiming(metapost) + input.starttiming(metapost.exectime) + local result = mpx:execute(format("beginfig(1);%s;endfig;",data)) + input.stoptiming(metapost.exectime) + if result.status > 0 then + print("error", result.status, result.error or result.term or result.log) + result = "" + else + result = metapost.filterclippath(result) + end + input.stoptiming(metapost) + sprint(result) + end +end + +metapost.tex = metapost.tex or { } + +do -- only used in graphictexts + + local environments = { } + + function metapost.tex.set(str) + environments[#environments+1] = str + end + function metapost.tex.reset() + environments = { } + end + function metapost.tex.get() + return concat(environments,"\n") + end + +end + +do -- not that beautiful but ok, we could save a md5 hash in the tui file ! + + local graphics = { } + local start = [[\starttext]] + local preamble = [[\long\def\MPLIBgraphictext#1{\startTEXpage[scale=10000]#1\stopTEXpage}]] + local stop = [[\stoptext]] + + function metapost.specials.gt(specification,object) -- number, so that we can reorder + graphics[#graphics+1] = format("\\MPLIBgraphictext{%s}",specification) + metapost.intermediate.needed = true + metapost.multipass = true + return { }, nil, nil, nil + end + + function metapost.intermediate.actions.makempy() + if #graphics > 0 then + local mpofile = tex.jobname .. "-mp" + local mpyfile = file.replacesuffix(mpofile,"mpy") + local pdffile = file.replacesuffix(mpofile,"pdf") + local texfile = file.replacesuffix(mpofile,"tex") + io.savedata(texfile, { start, preamble, metapost.tex.get(), concat(graphics,"\n"), stop }, "\n") + os.execute(format("context --once %s", texfile)) + if io.exists(pdffile) then + os.execute(format("pstoedit -ssp -dt -f mpost %s %s", pdffile, mpyfile)) + local result = { } + if io.exists(mpyfile) then + local data = io.loaddata(mpyfile) + for figure in data:gmatch("beginfig(.-)endfig") do + result[#result+1] = format("begingraphictextfig%sendgraphictextfig ;\n", figure) + end + io.savedata(mpyfile,concat(result,"")) + end + end + graphics = { } + end + end + +end |