diff options
author | Hans Hagen <pragma@wxs.nl> | 2018-04-13 15:51:39 +0200 |
---|---|---|
committer | Context Git Mirror Bot <phg42.2a@gmail.com> | 2018-04-13 15:51:39 +0200 |
commit | 25fcad7435f56cdce2658336909f4da6a65589c0 (patch) | |
tree | c23d5d04a7e86c7ddc2ebeca06d3de63ebdc806e /tex/context/base/mkiv/meta-blb.lua | |
parent | 1e5d7f41ddede5e6400a2a7762032823d3545df4 (diff) | |
download | context-25fcad7435f56cdce2658336909f4da6a65589c0.tar.gz |
2018-04-13 15:02:00
Diffstat (limited to 'tex/context/base/mkiv/meta-blb.lua')
-rw-r--r-- | tex/context/base/mkiv/meta-blb.lua | 305 |
1 files changed, 305 insertions, 0 deletions
diff --git a/tex/context/base/mkiv/meta-blb.lua b/tex/context/base/mkiv/meta-blb.lua new file mode 100644 index 000000000..202c2850b --- /dev/null +++ b/tex/context/base/mkiv/meta-blb.lua @@ -0,0 +1,305 @@ +if not modules then modules = { } end modules ['meta-blb'] = { + version = 1.001, + comment = "companion to mlib-ctx.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files", +} + +-- This could be integrated in other modules but for me it also serves +-- as an example of usign the plugin mechanism. + +local tonumber = tonumber + +local setmetatableindex = table.setmetatableindex +local insert, remove = table.insert, table.remove + +local topoints = number.topoints +local mpprint = mp.print +local mpinteger = mp.integer +local mppoints = mp.points +local mptriplet = mp.triplet +local mptripletpoints = mp.tripletpoints + +local texsetbox = tex.setbox +local toutf = nodes.toutf +local hpack_nodes = nodes.hpack + +local trace = false +local report = logs.reporter("metapost","blobs") + +trackers.register("metapost.blobs", function(v) trace = v end) + +-- We start with a text that comes from an analyze stage and can end up with +-- one or more results. For practical reasons we store the blobs in one array +-- and work with ranges. + +local allblobs = { } + +local function newcategory(t,k) + if trace then + report("new category %a",k) + end + local v = { + name = k, + text = "", + blobs = { }, + } + t[k] = v + return v +end + +local texblobs = setmetatableindex(newcategory) + +local function blob_raw_reset(category) + -- we need to keep the allblobs + if category then + if trace then + report("reset category %a",category) + end + texblobs[category] = nil + else + if trace then + report("reset all") + end + texblobs = setmetatableindex(newcategory) + end +end + +local function blob_raw_dimensions(i) + local blob = allblobs[i] + if blob then + return blob.width, blob.height, blob.depth + else + return 0, 0, 0 + end +end + +local function blob_raw_content(i) + return allblobs[i] +end + +local function blob_raw_toutf(i) + return toutf(allblobs[i]) +end + +local function blob_raw_wipe(i) + allblobs[i] = false +end + +mp.blob_raw_dimensions = blob_raw_dimensions +mp.blob_raw_content = blob_raw_content +mp.blob_raw_reset = blob_raw_reset +mp.blob_raw_wipe = blob_raw_wipe +mp.blob_raw_toutf = blob_raw_toutf + +function mp.blob_new(category,text) + if trace then + report("category %a, text %a",category,text) + end + texblobs[category].text = text +end + +function mp.blob_add(category,blob) + local tb = texblobs[category].blobs + local tn = #allblobs + 1 + blob = hpack_nodes(blob) + allblobs[tn] = blob + tb[#tb+1] = tn + if trace then + report("category %a, blob %a set, content %a",category,tn,blob_raw_toutf(tn)) + end +end + +function mp.blob_width(category,i) + local index = texblobs[category].blobs[i] + local blob = allblobs[index] + if blob then + mppoints(blob.width or 0) + else + mpinteger(0) + end +end + +function mp.blob_size(category,i) + mpprint(#texblobs[category].blobs or 0) +end + +function mp.blob_index(category,i) + mpprint(texblobs[category].blobs[i] or 0) +end + +function mp.blob_dimensions(category,i) + local index = texblobs[category].blobs[i] + local blob = allblobs[index] + if blob then + mptripletpoints(blob.width,blob.height,blob.depth) + else + mptriplet(0,0,0) + end +end + +local f_f = string.formatters["%F"] +local sxsy = metapost.sxsy +local cm = metapost.cm + +local function injectblob(object,blob) + local sx, rx, ry, sy, tx, ty = cm(object) + local wd, ht, dp = blob_raw_dimensions(blob) + if wd then + object.path = false + object.color = false + object.grouped = true + object.istext = true + return function() + if trace then + report("injecting blob %a, width %p, heigth %p, depth %p, text %a",blob,wd,ht,dp,blob_raw_toutf(blob)) + end + context.MPLIBgetblobscaledcm(blob, + f_f(sx), f_f(rx), f_f(ry), + f_f(sy), f_f(tx), f_f(ty), + sxsy(wd,ht,dp)) + end + end +end + +mp.blob_inject = injectblob + +local function getblob(box,blob) + texsetbox(box,blob_raw_content(blob)) + blob_raw_wipe(blob) +end + +interfaces.implement { + name = "mpgetblob", + actions = getblob, + arguments = { "integer", "integer" }, +} + +-- the plug: + +local function reset() + blob_raw_reset() +end + +local function analyze(object,prescript) + -- nothing +end + +local function process(object,prescript,before,after) + if prescript.tb_stage == "inject" then + local tb_blob = tonumber(prescript.tb_blob) + if tb_blob then + before[#before+1] = injectblob(object,tb_blob) + end + end +end + +metapost.installplugin(reset,analyze,process) + +-- Here follows an example of usage of the above: a more modern +-- version of followokens (in meta-imp-txt.mkiv). + +local nodecodes = nodes.nodecodes +local kerncodes = nodes.kerncodes + +local glue_code = nodecodes.glue +local kern_code = nodecodes.kern +local c_userkern = kerncodes.userkern +local c_fontkern = kerncodes.fontkern +local c_italickern = kerncodes.italickern +local a_fontkern = attributes.private("fontkern") + +local takebox = tex.takebox +local flatten_list = node.flatten_discretionaries +local remove_node = nodes.remove +local flush_node = nodes.flush + +local addblob = mp.blob_add +local newblob = mp.blob_new + +local visible_code = { + [nodecodes.glyph] = true, + [nodecodes.glue] = true, + [nodecodes.hlist] = true, + [nodecodes.vlist] = true, + [nodecodes.rule] = true, +} + +local function initialize(category,box) + local wrap = takebox(box) + if wrap then + local head = wrap.list + local tail = nil + local temp = nil + if head then + local n = { } + local s = 0 + head = flatten_list(head) + local current = head + while current do + local id = current.id + if visible_code[id] then + head, current, tail = remove_node(head,current) + s = s + 1 + n[s] = tail + elseif id == kern_code then + local subtype = current.subtype + if subtype == c_fontkern or subtype == italickern then -- or current[a_fontkern] + head, current, temp = remove_node(head,current) + tail.next = temp + temp.prev = tail + tail = temp + else + head, current, temp = remove_node(head,current) + s = s + 1 + n[s] = temp + end + elseif id == glue_code then + head, current, temp = remove_node(head,current) + s = s + 1 + n[s] = temp + else + current = current.next + end + end + for i=1,s do + n[i] = addblob(category,n[i]) + end + wrap.list = head + end + flush_node(wrap) + end +end + +interfaces.implement { + name = "MPLIBconvertfollowtext", + arguments = { "integer","integer" }, + actions = initialize, +} + +local function reset() + -- nothing +end + +local function analyze(object,prescript) + if prescript.ft_stage == "trial" then + local ft_category = tonumber(prescript.ft_category) + if ft_category then + newblob(ft_category,object.postscript) -- only for tracing + context.MPLIBfollowtext(ft_category,object.postscript) + metapost.getjobdata().multipass = true + end + end +end + +local function process(object,prescript,before,after) + if prescript.ft_stage == "final" then + object.path = false + object.color = false + object.grouped = true + object.istext = true + end +end + +metapost.installplugin(reset,analyze,process) |