diff options
author | Hans Hagen <pragma@wxs.nl> | 2021-10-19 00:16:55 +0200 |
---|---|---|
committer | Context Git Mirror Bot <phg@phi-gamma.net> | 2021-10-19 00:16:55 +0200 |
commit | 9d2ad7dea5c20379f6679c57c3b16752b1af445a (patch) | |
tree | 45f39853be982c52f7386b968cf4f15f1f70ccce /tex/context/base/mkxl/back-imp-lua.lmt | |
parent | 6ca88e6f1f15cea89db047839c3126a501f39eea (diff) | |
download | context-9d2ad7dea5c20379f6679c57c3b16752b1af445a.tar.gz |
2021-10-18 23:13:00
Diffstat (limited to 'tex/context/base/mkxl/back-imp-lua.lmt')
-rw-r--r-- | tex/context/base/mkxl/back-imp-lua.lmt | 378 |
1 files changed, 378 insertions, 0 deletions
diff --git a/tex/context/base/mkxl/back-imp-lua.lmt b/tex/context/base/mkxl/back-imp-lua.lmt new file mode 100644 index 000000000..5bb23973c --- /dev/null +++ b/tex/context/base/mkxl/back-imp-lua.lmt @@ -0,0 +1,378 @@ +if not modules then modules = { } end modules ['back-imp-lua'] = { + version = 1.001, + optimize = true, + comment = "companion to back-imp-lua.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- we can remap fonts + +local fontproperties = fonts.hashes.properties +local fontparameters = fonts.hashes.parameters +local fontshapes = fonts.hashes.shapes + +local starttiming = statistics.starttiming +local stoptiming = statistics.stoptiming + +local bpfactor = number.dimenfactors.bp +local texgetbox = tex.getbox + +local rulecodes = nodes.rulecodes +local normalrule_code = rulecodes.normal +----- boxrule_code = rulecodes.box +----- imagerule_code = rulecodes.image +----- emptyrule_code = rulecodes.empty +----- userrule_code = rulecodes.user +----- overrule_code = rulecodes.over +----- underrule_code = rulecodes.under +----- fractionrule_code = rulecodes.fraction +----- radicalrule_code = rulecodes.radical +local outlinerule_code = rulecodes.outline + +-- todo : per instance + +local pages = { } +local fonts = { } +local names = { } +local mapping = { } +local used = { } +local shapes = { } +local glyphs = { } +local buffer = { } +local metadata = nil +local b = 0 +local converter = nil + +local compact = false -- true +local shapestoo = true + +local x, y, d, f, c, w, h, t, r, o + +local function reset() + buffer = { } + b = 0 + t = nil + x = nil + y = nil + d = nil + f = nil + c = nil + w = nil + h = nil + r = nil + o = nil +end + +local function result() + return { + metadata = metadata, + fonts = fonts, + pages = pages, + shapes = shapes, + } +end + +-- actions + +local function outputfilename(driver) + return tex.jobname .. "-output.lua" +end + +local function save() -- might become a driver function that already is plugged into stopactions + local filename = outputfilename() + drivers.report("saving result in %a",filename) + starttiming(drivers) + local data = result() + if data then + io.savedata(filename,table.serialize(data)) + end + stoptiming(drivers) +end + +local function prepare(driver) + converter = drivers.converters.lmtx + -- if not environment.initex then + backends.initialize("lua") + -- end + luatex.registerstopactions(1,function() + save() + end) +end + +local function initialize(driver,details) + reset() +end + +local function finalize(driver,details) + local n = details.pagenumber + local b = details.boundingbox + pages[n] = { + number = n, + content = buffer, + boundingbox = { + b[1] * bpfactor, + b[2] * bpfactor, + b[3] * bpfactor, + b[4] * bpfactor, + }, + } + if not metadata then + -- this has to happen while we're still running tex because we do + -- prerolls + local identity = interactions.general.getidentity() + local jobname = environment.jobname or tex.jobname or "unknown" + metadata = { + unit = "bp", + jobname = jobname, + title = identity.title, + subject = identity.subject, + author = identity.author, + keywords = identity.keywords, + time = os.date("%Y-%m-%d %H:%M"), + engine = environment.luatexengine .. " " .. environment.luatexversion, + context = environment.version, + } + end +end + +local function wrapup(driver) +end + +local function cleanup(driver) + reset() +end + +local function convert(driver,boxnumber,pagenumber) + converter(driver,texgetbox(boxnumber),"page",pagenumber) +end + +-- flushers + +local function updatefontstate(id) + if not mapping[id] then + local fn = #fonts + 1 + mapping[id] = fn + local properties = fontproperties[id] + local parameters = fontparameters[id] + local filename = file.basename(properties.filename) + local fontname = properties.fullname or properties.fontname + if shapestoo then + if not names[fontname] then + local sn = #shapes+1 + names[fontname] = sn + shapes[sn] = { } + glyphs[sn] = fontshapes[id].glyphs + end + end + fonts[fn] = { + filename = filename, + name = fontname, + size = parameters.size * bpfactor, + shapes = shapestoo and names[fontname] or nil, + } + end +end + +local function flushcharacter(current, pos_h, pos_v, pos_r, font, char) + local fnt = mapping[font] + b = b + 1 + buffer[b] = { + t = "glyph" ~= t and "glyph" or nil, + f = font ~= f and fnt or nil, + c = char ~= c and char or nil, + x = pos_h ~= x and (pos_h * bpfactor) or nil, + y = pos_v ~= y and (pos_v * bpfactor) or nil, + d = pos_r ~= d and (pos_r == 1 and "r2l" or "l2r") or nil, + } + t = "glyph" + f = font + c = char + x = pos_h + y = pos_v + d = pos_r + if shapestoo then + -- can be sped up if needed + local sn = fonts[fnt].shapes + local shp = shapes[sn] + if not shp[char] then + shp[char] = glyphs[sn][char] + end + end +end + +local function flush_rule(current, pos_h, pos_v, pos_r, size_h, size_v, rule_s, rule_o) + b = b + 1 + buffer[b] = { + t = "rule" ~= t and "rule" or nil, + r = rule_s ~= r and rule_s or nil, + o = rule_s == "outline" and rule_o ~= o and (rule_o * bpfactor) or nil, + w = size_h ~= w and (size_h * bpfactor) or nil, + h = size_v ~= h and (size_v * bpfactor) or nil, + x = pos_h ~= x and (pos_h * bpfactor) or nil, + y = pos_v ~= y and (pos_v * bpfactor) or nil, + d = pos_r ~= d and (pos_r == 1 and "r2l" or "l2r") or nil, + } + t = "rule" + w = size_h + h = size_v + x = pos_h + y = pos_v + d = pos_r +end + +local function flushrule(current, pos_h, pos_v, pos_r, size_h, size_v, subtype) + local rule_s, rule_o + if subtype == normalrule_code then + rule_s = normal_rule_code + elseif subtype == outlinerule_code then + rule_s = outline_rule_code + rule_o = getdata(current) + else + return + end + return flush_rule(pos_h, pos_v, pos_r, size_h, size_v, rule_s, rule_o) +end + +local function flushsimplerule(pos_h, pos_v, pos_r, size_h, size_v) + return flush_rule(false,pos_h,pos_v,pos_r,size_h,size_v,normalrule_code,nil) +end + +local function flushspecialrule(pos_h, pos_v, pos_r, w, h, d, l, outline) + return flush_rule(false,pos_h,pos_v-d,pos_r,w,h+d,outline and outlinerule_code or normalrule_code) +end + +-- file stuff too +-- todo: default flushers +-- also color (via hash) + +-- installer + +drivers.install { + name = "lua", + actions = { + prepare = prepare, + initialize = initialize, + finalize = finalize, + wrapup = wrapup, + cleanup = cleanup, + convert = convert, + outputfilename = outputfilename, + }, + flushers = { + updatefontstate = updatefontstate, + character = flushcharacter, + rule = flushrule, + simplerule = flushsimplerule, + specialrule = flushspecialrule, + } +} + +-- actions + +local function outputfilename(driver) + return tex.jobname .. "-output.json" +end + +local function save() -- might become a driver function that already is plugged into stopactions + local filename = outputfilename() + drivers.report("saving result in %a",filename) + starttiming(drivers) + local data = result() + if data then + if not utilities.json then + require("util-jsn") + end + io.savedata(filename,utilities.json.tostring(data,not compact)) + end + stoptiming(drivers) +end + +local function prepare(driver) + converter = drivers.converters.lmtx + luatex.registerstopactions(1,function() + save() + end) +end + +-- installer + +drivers.install { + name = "json", + actions = { + prepare = prepare, + wrapup = wrapup, + cleanup = cleanup, + -- + initialize = initialize, + convert = convert, + finalize = finalize, + -- + outputfilename = outputfilename, + }, + flushers = { + updatefontstate = updatefontstate, + character = flushcharacter, + rule = flushrule, + simplerule = flushsimplerule, + specialrule = flushspecialrule, + setstate = function() end, + } +} + +-- actions + +local function outputfilename(driver) + return tex.jobname .. "-output.js" +end + +local function save() -- might become a driver function that already is plugged into stopactions + local filename = outputfilename() + drivers.report("saving result in %a",filename) + starttiming(drivers) + local data = result() + if data then + if not utilities.json then + require("util-jsn") + end + io.savedata(filename, + "const JSON_CONTEXT = JSON.parse ( `" .. + utilities.json.tostring(data,not compact) .. + "` ) ;\n" + ) + end + stoptiming(drivers) +end + +local function prepare(driver) + converter = drivers.converters.lmtx + -- if not environment.initex then + backends.initialize("js") + -- end + luatex.registerstopactions(1,function() + save() + end) +end + +-- installer + +drivers.install { + name = "js", + actions = { + prepare = prepare, + initialize = initialize, + finalize = finalize, + wrapup = wrapup, + cleanup = cleanup, + convert = convert, + outputfilename = outputfilename, + }, + flushers = { + updatefontstate = updatefontstate, + character = flushcharacter, + rule = flushrule, + simplerule = flushsimplerule, + specialrule = flushspecialrule, + } +} |