diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/mkxl/lpdf-rul.lmt')
-rw-r--r-- | Master/texmf-dist/tex/context/base/mkxl/lpdf-rul.lmt | 388 |
1 files changed, 388 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/context/base/mkxl/lpdf-rul.lmt b/Master/texmf-dist/tex/context/base/mkxl/lpdf-rul.lmt new file mode 100644 index 00000000000..efcc6207372 --- /dev/null +++ b/Master/texmf-dist/tex/context/base/mkxl/lpdf-rul.lmt @@ -0,0 +1,388 @@ +if not modules then modules = { } end modules ['lpdf-rul'] = { + version = 1.001, + comment = "companion to grph-rul.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local tonumber, next, type = tonumber, next, type +local concat = table.concat + +local attributes = attributes +local nodes = nodes + +local bpfactor = number.dimenfactors.bp + +local nuts = nodes.nuts +local ruleactions = nuts.rules.ruleactions + +local getwhd = nuts.getwhd + +local lefttoright_code = nodes.dirvalues.lefttoright + +local mpcolor = attributes.colors.mpcolor + +local trace_mp = false trackers.register("rules.mp", function(v) trace_mp = v end) + +local report_mp = logs.reporter("rules","mp") + +local floor = math.floor +local getrandom = utilities.randomizer.get +local formatters = string.formatters + +-- This is very pdf specific. Maybe move some to lpdf-rul.lua some day. + +local pdfprint ; pdfprint = function(...) pdfprint = lpdf.print return pdfprint(...) end + +-- updaters.register("backend.update",function() pdfprint = lpdf.print end) + +do + + local simplemetapost = metapost.simple + local cachesize = 0 + local maxcachesize = 256*1024 + local cachethreshold = 1024 + local caching = false -- otherwise random issues so we need a dedicated randomizer first + + -- local maxcachesize = 8*1024 + -- local cachethreshold = 1024/2 + + local cache = table.setmetatableindex(function(t,k) + local v = simplemetapost("rulefun",k) -- w, h, d + cachesize = cachesize + #v + if cachesize > maxcachesize then + -- print("old",cachesize) + for k, v in next, t do + local n = #v + if n > cachethreshold then + t[k] = nil + cachesize = cachesize - n + end + end + -- print("new",cachesize) + end + -- print(cachesize,maxcachesize,cachethreshold,#v) + t[k] = v + return v + end) + + local replacer = utilities.templates.replacer + + -- todo: RuleColor -> just string ? + + local predefined = { + ["fake:word"] = replacer [[ +FakeWord(%width%,%height%,%depth%,%line%,%color%); + ]], + ["fake:rule"] = replacer[[ +%initializations% +FakeRule(%width%,%height%,%depth%,%line%,%color%); + ]], + ["fake:rest"] = replacer [[ +RuleDirection := "%direction%" ; +RuleOption := "%option%" ; +RuleWidth := %width% ; +RuleHeight := %height% ; +RuleDepth := %depth% ; +RuleH := %h% ; +RuleV := %v% ; +RuleThickness := %line% ; +RuleFactor := %factor% ; +RuleOffset := %offset% ; +def RuleColor = %color% enddef ; +%data%; + ]] + } + + local initialized = false ; + + local rule_mp = function(p,h,v,i,n) + local name = p.name or "fake:rest" + local code = (predefined[name] or predefined["fake:rest"]) { + data = p.data or "", + width = p.width * bpfactor, + height = p.height * bpfactor, + depth = p.depth * bpfactor, + factor = (p.factor or 0) * bpfactor, -- needs checking + offset = p.offset or 0, + line = (p.line or 65536) * bpfactor, + color = mpcolor(p.ma,p.ca,p.ta), + option = p.option or "", + direction = p.direction or lefttoright_code, + h = h * bpfactor, + v = v * bpfactor, + } + if not initialized then + initialized = true + simplemetapost("rulefun",formatters["randomseed := %s;"](getrandom("rulefun",0,4095))) + end + -- we enable extensions but we could also consider to delegate colors + -- to the node finalizer + local pdf = caching and cache[code] or simplemetapost("rulefun",code,true) + if trace_mp then + report_mp("code: %s",code) + report_mp("pdf : %s",pdf) + end + if pdf and pdf ~= "" then + pdfprint("direct",pdf) + end + end + + updaters.register("backend.update.lpdf",function() + ruleactions.mp = rule_mp + end) + +end + +do + + -- This is the old oval method that we keep it for compatibility reasons. Of + -- course one can use mp instead. It could be improved but at the cost of more + -- code than I'm willing to add for something hardly used. + + local function round(p,kind) + local method = tonumber(p.corner) or 0 + if method < 0 or method > 27 then + method = 0 + end + local width = p.width or 0 + local height = p.height or 0 + local depth = p.depth or 0 + local total = height + depth + local radius = p.radius or 655360 + local line = p.line or 65536 + local how = (method > 8 or kind ~= "fill") and "S" or "f" + local half = line / 2 + local xmin = half * bpfactor + local xmax = ( width - half) * bpfactor + local ymax = ( height - half) * bpfactor + local ymin = (-depth + half) * bpfactor + local full = ( radius + half) + local xxmin = full * bpfactor + local xxmax = ( width - full) * bpfactor + local yymax = ( height - full) * bpfactor + local yymin = (-depth + full) * bpfactor + line = line * bpfactor + if xxmin <= xxmax and yymin <= yymax then + local list = nil + if method == 0 then + list = { + "q", line, "w", xxmin, ymin, "m", xxmax, ymin, "l", xmax, ymin, xmax, yymin, "y", + xmax, yymax, "l", xmax, ymax, xxmax, ymax, "y", xxmin, ymax, "l", xmin, ymax, + xmin, yymax, "y", xmin, yymin, "l", xmin, ymin, xxmin, ymin, "y", "h", how, "Q", + } + elseif method == 1 then + list = { + "q", line, "w", xxmin, ymin, "m", xxmax, ymin, "l", xmax, ymin, xmax, yymin, "y", + xmax, ymax, "l", xmin, ymax, "l", xmin, yymin, "l", xmin, ymin, xxmin, ymin, "y", + "h", how, "Q", + } + elseif method == 2 then + list = { + "q", line, "w", xxmin, ymin, "m", xmax, ymin, "l", xmax, ymax, "l", xxmin, ymax, + "l", xmin, ymax, xmin, yymax, "y", xmin, yymin, "l", xmin, ymin, xxmin, ymin, + "y", "h", how, "Q", + } + elseif method == 3 then + list = { + "q", line, "w", xmin, ymin, "m", xmax, ymin, "l", xmax, yymax, "l", xmax, ymax, + xxmax, ymax, "y", xxmin, ymax, "l", xmin, ymax, xmin, yymax, "y", xmin, ymin, + "l", "h", how, "Q", + } + + elseif method == 4 then + list = { + "q", line, "w", xmin, ymin, "m", xxmax, ymin, "l", xmax, ymin, xmax, yymin, "y", + xmax, yymax, "l", xmax, ymax, xxmax, ymax, "y", xmin, ymax, "l", xmin, ymin, "l", + "h", how, "Q", + } + elseif method == 5 then + list = { + "q", line, "w", xmin, ymin, "m", xmax, ymin, "l", xmax, yymax, "l", xmax, ymax, + xxmax, ymax, "y", xmin, ymax, "l", xmin, ymin, "l", "h", how, "Q", + } + elseif method == 6 then + list = { + "q", line, "w", xmin, ymin, "m", xxmax, ymin, "l", xmax, ymin, xmax, yymin, "y", + xmax, ymax, "l", xmin, ymax, "l", xmin, ymin, "l", "h", how, "Q", + } + elseif method == 7 then + list = { + "q", line, "w", xxmin, ymin, "m", xmax, ymin, "l", xmax, ymax, "l", xmin, ymax, + "l", xmin, yymin, "l", xmin, ymin, xxmin, ymin, "y", "h", how, "Q", + } + elseif method == 8 then + list = { + "q", line, "w", xmin, ymin, "m", xmax, ymin, "l", xmax, ymax, "l", xxmin, ymax, + "l", xmin, ymax, xmin, yymax, "y", xmin, ymin, "l", "h", how, "Q", + } + elseif method == 9 then + list = { + "q", line, "w", xmin, ymax, "m", xmin, yymin, "l", xmin, ymin, xxmin, ymin, "y", + xxmax, ymin, "l", xmax, ymin, xmax, yymin, "y", xmax, ymax, "l", how, "Q", + } + elseif method == 10 then + list = { + "q", line, "w", xmax, ymax, "m", xxmin, ymax, "l", xmin, ymax, xmin, yymax, "y", + xmin, yymin, "l", xmin, ymin, xxmin, ymin, "y", xmax, ymin, "l", how, "Q", + } + elseif method == 11 then + list = { + "q", line, "w", xmax, ymin, "m", xmax, yymax, "l", xmax, ymax, xxmax, ymax, "y", + xxmin, ymax, "l", xmin, ymax, xmin, yymax, "y", xmin, ymin, "l", how, "Q", + } + elseif method == 12 then + list = { + "q", line, "w", xmin, ymax, "m", xxmax, ymax, "l", xmax, ymax, xmax, yymax, "y", + xmax, yymin, "l", xmax, ymin, xxmax, ymin, "y", xmin, ymin, "l", how, "Q", + } + elseif method == 13 then + list = { + "q", line, "w", xmin, ymax, "m", xxmax, ymax, "l", xmax, ymax, xmax, yymax, "y", + xmax, ymin, "l", how, "Q", + } + elseif method == 14 then + list = { + "q", line, "w", xmax, ymax, "m", xmax, yymin, "l", xmax, ymin, xxmax, ymin, "y", + xmin, ymin, "l", how, "Q", + } + elseif method == 15 then + list = { + "q", line, "w", xmax, ymin, "m", xxmin, ymin, "l", xmin, ymin, xmin, yymin, "y", + xmin, ymax, "l", how, "Q", + } + elseif method == 16 then + list = { + "q", line, "w", xmin, ymin, "m", xmin, yymax, "l", xmin, ymax, xxmin, ymax, "y", + xmax, ymax, "l", how, "Q", + } + elseif method == 17 then + list = { + "q", line, "w", xxmax, ymax, "m", xmax, ymax, xmax, yymax, "y", how, "Q", + } + elseif method == 18 then + list = { + "q", line, "w", xmax, yymin, "m", xmax, ymin, xxmax, ymin, "y", how, "Q", + } + elseif method == 19 then + list = { + "q", line, "w", xxmin, ymin, "m", xmin, ymin, xmin, yymin, "y", how, "Q", + } + elseif method == 20 then + list = { + "q", line, "w", xmin, yymax, "m", xmin, ymax, xxmin, ymax, "y", how, "Q", + } + elseif method == 21 then + list = { + "q", line, "w", xxmax, ymax, "m", xmax, ymax, xmax, yymax, "y", xmin, yymax, "m", + xmin, ymax, xxmin, ymax, "y", how, "Q", + } + elseif method == 22 then + list = { + "q", line, "w", xxmax, ymax, "m", xmax, ymax, xmax, yymax, "y", xmax, yymin, "m", + xmax, ymin, xxmax, ymin, "y", how, "Q", + } + elseif method == 23 then + list = { + "q", line, "w", xmax, yymin, "m", xmax, ymin, xxmax, ymin, "y", xxmin, ymin, "m", + xmin, ymin, xmin, yymin, "y", how, "Q", + } + elseif method == 24 then + list = { + "q", line, "w", xxmin, ymin, "m", xmin, ymin, xmin, yymin, "y", xmin, yymax, "m", + xmin, ymax, xxmin, ymax, "y", how, "Q", + } + elseif method == 25 then + list = { + "q", line, "w", xxmax, ymax, "m", xmax, ymax, xmax, yymax, "y", xmax, yymin, "m", + xmax, ymin, xxmax, ymin, "y", xxmin, ymin, "m", xmin, ymin, xmin, yymin, "y", + xmin, yymax, "m", xmin, ymax, xxmin, ymax, "y", how, "Q", + } + elseif method == 26 then + list = { + "q", line, "w", xmax, yymin, "m", xmax, ymin, xxmax, ymin, "y", xmin, yymax, "m", + xmin, ymax, xxmin, ymax, "y", how, "Q", + } + + elseif method == 27 then + list = { + "q", line, "w", xxmax, ymax, "m", xmax, ymax, xmax, yymax, "y", xxmin, ymin, "m", + xmin, ymin, xmin, yymin, "y", how, "Q", + } + end + pdfprint("direct",concat(list," ")) + end + end + + local f_rectangle = formatters["%.6N w %.6N %.6N %.6N %.6N re %s"] + local f_baselined = formatters["%.6N w %.6N %.6N %.6N %.6N re s %.6N %.6N m %.6N %.6N l s"] + local f_dashlined = formatters["%.6N w %.6N %.6N %.6N %.6N re s [%.6N %.6N] 2 d %.6N %.6N m %.6N %.6N l s"] + local f_radtangle = formatters[ +[[%.6N w %.6N %.6N m +%.6N %.6N l %.6N %.6N %.6N %.6N y +%.6N %.6N l %.6N %.6N %.6N %.6N y +%.6N %.6N l %.6N %.6N %.6N %.6N y +%.6N %.6N l %.6N %.6N %.6N %.6N y +h %s]] + ] + + local rule_any = function(p,h,v,i,n) + if p.corner then + return round(p,i) + else + local l = (p.line or 65536)*bpfactor + local r = p and (p.radius or 0)*bpfactor or 0 + local w = h * bpfactor + local h = v * bpfactor + local m = nil + local t = i == "fill" and "f" or "s" + local o = l / 2 + if r > 0 then + w = w - o + h = h - o + m = f_radtangle(l, r,o, w-r,o, w,o,w,r, w,h-r, w,h,w-r,h, r,h, o,h,o,h-r, o,r, o,o,r,o, t) + else + w = w - l + h = h - l + m = f_rectangle(l,o,o,w,h,t) + end + pdfprint("direct",m) + end + end + + local function rule_box(p,h,v,i,n) + local w, h, d = getwhd(n) + local line = p.line or 65536 + local l = line *bpfactor + local w = w * bpfactor + local h = h * bpfactor + local d = d * bpfactor + local o = l / 2 + if (d >= 0 and h >= 0) or (d <= 0 and h <= 0) then + local dashed = tonumber(p.dashed) + if dashed and dashed > 5*line then + dashed = dashed * bpfactor + local delta = (w - 2*dashed*floor(w/(2*dashed)))/2 + pdfprint("direct",f_dashlined(l,o,o,w-l,h+d-l,dashed,dashed,delta,d,w-delta,d)) + else + pdfprint("direct",f_baselined(l,o,o,w-l,h+d-l,0,d,w,d)) + end + else + pdfprint("direct",f_rectangle(l,o,o,w-l,h+d-l)) + end + end + + updaters.register("backend.update.lpdf",function() + ruleactions.fill = rule_any + ruleactions.draw = rule_any + ruleactions.stroke = rule_any + ruleactions.box = rule_box + end) + +end + + + ruleactions.mp = unsupported + + |