summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/luatex/luamplib/luamplib.lua
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2013-05-12 22:38:13 +0000
committerKarl Berry <karl@freefriends.org>2013-05-12 22:38:13 +0000
commit8907d5d0eb9a9b630b813f7d0ae7e406a1c4cb01 (patch)
treec075608e0fa6fbccc05bda8a8df1145ecca49cc9 /Master/texmf-dist/tex/luatex/luamplib/luamplib.lua
parent0d9028560da113b542d8cd721f3164a00d492de2 (diff)
luamplib (12may13)
git-svn-id: svn://tug.org/texlive/trunk@30423 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/luatex/luamplib/luamplib.lua')
-rw-r--r--Master/texmf-dist/tex/luatex/luamplib/luamplib.lua314
1 files changed, 233 insertions, 81 deletions
diff --git a/Master/texmf-dist/tex/luatex/luamplib/luamplib.lua b/Master/texmf-dist/tex/luatex/luamplib/luamplib.lua
index 71c45d440d7..45e7ceff864 100644
--- a/Master/texmf-dist/tex/luatex/luamplib/luamplib.lua
+++ b/Master/texmf-dist/tex/luatex/luamplib/luamplib.lua
@@ -8,31 +8,47 @@
--
-- See source file 'luamplib.dtx' for licencing and contact information.
--
-module('luamplib', package.seeall)
+
+luamplib = luamplib or { }
+
+
+local luamplib = luamplib
+luamplib.showlog = luamplib.showlog or false
+luamplib.lastlog = ""
+
local err, warn, info, log = luatexbase.provides_module({
name = "luamplib",
- version = 1.09,
- date = "2011/11/09",
+ version = 2.00,
+ date = "2013/05/07",
description = "Lua package to typeset Metapost with LuaTeX's MPLib.",
})
-local function term(...)
- texio.write_nl('term', 'luamplib: ' .. string.format(...))
-end
-local format, concat, abs = string.format, table.concat, math.abs
+local format, abs = string.format, math.abs
-local data = ""
+local stringgsub = string.gsub
+local stringfind = string.find
+local stringmatch = string.match
+local stringgmatch = string.gmatch
+local tableconcat = table.concat
+local texsprint = tex.sprint
-local function resetdata()
- data = ""
-end
-function addline(line)
- data = data .. '\n' .. line
-end
-function processlines()
- process(data)
- resetdata()
+local mplib = require ('mplib')
+local kpse = require ('kpse')
+
+local file = file
+if not file then
+
+
+ file = { }
+
+ function file.replacesuffix(filename, suffix)
+ return (stringgsub(filename,"%.[%a%d]+$","")) .. "." .. suffix
+ end
+
+ function file.stripsuffix(filename)
+ return (stringgsub(filename,"%.[%a%d]+$",""))
+ end
end
local mpkpse = kpse.new("luatex", "mpost")
@@ -44,111 +60,177 @@ local function finder(name, mode, ftype)
return mpkpse:find_file(name,ftype)
end
end
+luamplib.finder = finder
-local currentformat = "plain"
-function setformat (name)
- currentformat = name
+function luamplib.resetlastlog()
+ luamplib.lastlog = ""
end
-function load()
- local mpx = mplib.new {
- find_file = finder,
- ini_version = true,
- }
- mpx:execute(format("input %s ;", currentformat))
- return mpx
+local mplibone = tonumber(mplib.version()) <= 1.50
+
+if mplibone then
+
+ luamplib.make = luamplib.make or function(name,mem_name,dump)
+ local t = os.clock()
+ local mpx = mplib.new {
+ ini_version = true,
+ find_file = luamplib.finder,
+ job_name = file.stripsuffix(name)
+ }
+ mpx:execute(format("input %s ;",name))
+ if dump then
+ mpx:execute("dump ;")
+ info("format %s made and dumped for %s in %0.3f seconds",mem_name,name,os.clock()-t)
+ else
+ info("%s read in %0.3f seconds",name,os.clock()-t)
+ end
+ return mpx
+ end
+
+ function luamplib.load(name)
+ local mem_name = file.replacesuffix(name,"mem")
+ local mpx = mplib.new {
+ ini_version = false,
+ mem_name = mem_name,
+ find_file = luamplib.finder
+ }
+ if not mpx and type(luamplib.make) == "function" then
+ -- when i have time i'll locate the format and dump
+ mpx = luamplib.make(name,mem_name)
+ end
+ if mpx then
+ info("using format %s",mem_name,false)
+ return mpx, nil
+ else
+ return nil, { status = 99, error = "out of memory or invalid format" }
+ end
+ end
+
+else
+
+
+ local preamble = [[
+ boolean mplib ; mplib := true ;
+ let dump = endinput ;
+ input %s ;
+ ]]
+
+ luamplib.make = luamplib.make or function()
+ end
+
+ function luamplib.load(name)
+ local mpx = mplib.new {
+ ini_version = true,
+ find_file = luamplib.finder,
+ }
+ local result
+ if not mpx then
+ result = { status = 99, error = "out of memory"}
+ else
+ result = mpx:execute(format(preamble, file.replacesuffix(name,"mp")))
+ end
+ luamplib.reporterror(result)
+ return mpx, result
+ end
+
+end
+
+local currentformat = "plain"
+
+local function setformat (name) --- used in .sty
+ currentformat = name
end
+luamplib.setformat = setformat
-function report(result)
+luamplib.reporterror = function (result)
if not result then
- err("no result object")
+ err("no result object returned")
elseif result.status > 0 then
- local t, e, l, f = result.term, result.error, result.log
- if l then
- log(l)
- end
+ local t, e, l = result.term, result.error, result.log
if t then
- term(t)
+ info(t)
end
if e then
- if result.status == 1 then
- warn(e)
- else
- err(e)
- end
+ err(e)
end
- if not t and not e and not l then
- if result.status == 1 then
- warn("unknown error, no error, terminal or log messages, maybe missing beginfig/endfig")
- else
- err("unknown error, no error, terminal or log messages, maybe missing beginfig/endfig")
- end
+ if not t and not e and l then
+ luamplib.lastlog = luamplib.lastlog .. "\n " .. l
+ log(l)
+ else
+ err("unknown, no error, terminal or log messages")
end
else
- return true
+ return false
end
- return false
+ return true
end
-function process(data)
+local function process_indeed (mpx, data)
local converted, result = false, {}
- local mpx = load()
+ local mpx = luamplib.load(mpx)
if mpx and data then
local result = mpx:execute(data)
- if report(result) then
- if result.fig then
- converted = convert(result)
- else
- warn("no figure output")
- end
+ if not result then
+ err("no result object returned")
+ elseif result.status > 0 then
+ err("%s",(result.term or "no-term") .. "\n" .. (result.error or "no-error"))
+ elseif luamplib.showlog then
+ luamplib.lastlog = luamplib.lastlog .. "\n" .. result.term
+ info("%s",result.term or "no-term")
+ elseif result.fig then
+ converted = luamplib.convert(result)
+ else
+ err("unknown error, maybe no beginfig/endfig")
end
else
err("Mem file unloadable. Maybe generated with a different version of mplib?")
end
return converted, result
end
+local process = function (data)
+ return process_indeed(currentformat, data)
+end
+luamplib.process = process
local function getobjects(result,figure,f)
return figure:objects()
end
-function convert(result, flusher)
- flush(result, flusher)
+local function convert(result, flusher)
+ luamplib.flush(result, flusher)
return true -- done
end
+luamplib.convert = convert
local function pdf_startfigure(n,llx,lly,urx,ury)
- tex.sprint(format("\\mplibstarttoPDF{%s}{%s}{%s}{%s}",llx,lly,urx,ury))
+ texsprint(format("\\mplibstarttoPDF{%f}{%f}{%f}{%f}",llx,lly,urx,ury))
end
local function pdf_stopfigure()
- tex.sprint("\\mplibstoptoPDF")
+ texsprint("\\mplibstoptoPDF")
end
-function pdf_literalcode(fmt,...) -- table
- tex.sprint(format("\\mplibtoPDF{%s}",format(fmt,...)))
+local function pdf_literalcode(fmt,...) -- table
+ texsprint(format("\\mplibtoPDF{%s}",format(fmt,...)))
end
+luamplib.pdf_literalcode = pdf_literalcode
-function pdf_textfigure(font,size,text,width,height,depth)
+local function pdf_textfigure(font,size,text,width,height,depth)
text = text:gsub(".","\\hbox{%1}") -- kerning happens in metapost
- tex.sprint(format("\\mplibtextext{%s}{%s}{%s}{%s}{%s}",font,size,text,0,-( 7200/ 7227)/65536*depth))
+ texsprint(format("\\mplibtextext{%s}{%f}{%s}{%s}{%f}",font,size,text,0,-( 7200/ 7227)/65536*depth))
end
+luamplib.pdf_textfigure = pdf_textfigure
local bend_tolerance = 131/65536
local rx, sx, sy, ry, tx, ty, divider = 1, 0, 0, 1, 0, 0, 1
local function pen_characteristics(object)
- if mplib.pen_info then
- local t = mplib.pen_info(object)
- rx, ry, sx, sy, tx, ty = t.rx, t.ry, t.sx, t.sy, t.tx, t.ty
- divider = sx*sy - rx*ry
- return not (sx==1 and rx==0 and ry==0 and sy==1 and tx==0 and ty==0), t.width
- else
- rx, sx, sy, ry, tx, ty, divider = 1, 0, 0, 1, 0, 0, 1
- return false, 1
- end
+ local t = mplib.pen_info(object)
+ rx, ry, sx, sy, tx, ty = t.rx, t.ry, t.sx, t.sy, t.tx, t.ty
+ divider = sx*sy - rx*ry
+ return not (sx==1 and rx==0 and ry==0 and sy==1 and tx==0 and ty==0), t.width
end
local function concat(px, py) -- no tx, ty here
@@ -227,15 +309,77 @@ local function flushconcatpath(path,open)
return t
end
-function flush(result,flusher)
+
+local mplibcodepreamble = [[
+vardef textext@#(expr n, w, h, d) =
+ image(
+ addto currentpicture doublepath unitsquare
+ xscaled w
+ yscaled (h+d)
+ withprescript "%%textext:"&decimal n&":"&decimal w&":"&decimal(h+d);
+ )
+enddef;
+]]
+
+local factor = 65536*(7227/7200)
+
+local function settexboxes (data)
+ local i = tex.count[14] -- newbox register
+ for _,c,_ in stringgmatch(data,"(%A)btex(%A.-%A)etex(%A)") do
+ i = i + 1
+ c = stringgsub(c,"^%s*(.-)%s*$","%1")
+ texsprint(format("\\setbox%i\\hbox{%s}",i,c))
+ end
+end
+
+luamplib.settexboxes = settexboxes
+
+local function gettexboxes (data)
+ local i = tex.count[14] -- the same newbox register
+ data = stringgsub(data,"(%A)btex%A.-%Aetex(%A)",
+ function(pre,post)
+ i = i + 1
+ local box = tex.box[i]
+ local boxmetr = format("textext(%i,%f,%f,%f)",
+ i,
+ box and (box.width/factor) or 0,
+ box and (box.height/factor) or 0,
+ box and (box.depth/factor) or 0)
+ return pre .. boxmetr .. post
+ end)
+ return mplibcodepreamble .. data
+end
+
+luamplib.gettexboxes = gettexboxes
+
+local function puttexboxes (object)
+ local n,tw,th = stringmatch(
+ object.prescript,
+ "%%%%textext:(%d+):([%d%.%+%-]+):([%d%.%+%-]+)")
+ if n and tw and th then
+ 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)/tw, (fourth.y_coord - ty)/th
+ local rx, ry = (second.y_coord - ty)/tw, (fourth.x_coord - tx)/th
+ if sx == 0 then sx = 0.00001 end
+ if sy == 0 then sy = 0.00001 end
+ pdf_literalcode("q %f %f %f %f %f %f cm",sx,rx,ry,sy,tx,ty)
+ texsprint(format("\\mplibputtextbox{%i}",n))
+ pdf_literalcode("Q")
+ end
+end
+
+
+local function flush(result,flusher)
if result then
local figures = result.fig
if figures then
for f=1, #figures do
- log("flushing figure %s",f)
+ info("flushing figure %s",f)
local figure = figures[f]
local objects = getobjects(result,figure,f)
- local fignum = tonumber((figure:filename()):match("([%d]+)$") or figure:charcode() or 0)
+ local fignum = tonumber(stringmatch(figure:filename(),"([%d]+)$") or figure:charcode() or 0)
local miterlimit, linecap, linejoin, dashed = -1, -1, -1, false
local bbox = figure:boundingbox()
local llx, lly, urx, ury = bbox[1], bbox[2], bbox[3], bbox[4] -- faster than unpack
@@ -248,9 +392,12 @@ function flush(result,flusher)
pdf_literalcode("q")
if objects then
for o=1,#objects do
- local object = objects[o]
- local objecttype = object.type
- if objecttype == "start_bounds" or objecttype == "stop_bounds" then
+ local object = objects[o]
+ local objecttype = object.type
+ local prescript = object.prescript --- [be]tex patch
+ if prescript and stringfind(prescript,"%%%%textext:") then
+ puttexboxes(object)
+ elseif objecttype == "start_bounds" or objecttype == "stop_bounds" then
-- skip
elseif objecttype == "start_clip" then
pdf_literalcode("q")
@@ -268,8 +415,11 @@ function flush(result,flusher)
pdf_literalcode("Q")
else
local cs = object.color
+ local cr = nil
if cs and #cs > 0 then
- pdf_literalcode(colorconverter(cs))
+ local start,stop = luamplib.colorconverter(cs)
+ pdf_literalcode(start)
+ cr = stop
end
local ml = object.miterlimit
if ml and ml ~= miterlimit then
@@ -288,7 +438,7 @@ function flush(result,flusher)
end
local dl = object.dash
if dl then
- local d = format("[%s] %i d",concat(dl.dashes or {}," "),dl.offset)
+ local d = format("[%s] %i d",tableconcat(dl.dashes or {}," "),dl.offset)
if d ~= dashed then
dashed = d
pdf_literalcode(dashed)
@@ -366,8 +516,9 @@ function flush(result,flusher)
end
end
end
+luamplib.flush = flush
-function colorconverter(cr)
+local function colorconverter(cr)
local n = #cr
if n == 4 then
local c, m, y, k = cr[1], cr[2], cr[3], cr[4]
@@ -380,5 +531,6 @@ function colorconverter(cr)
return format("%.3f g %.3f G",s,s), "0 g 0 G"
end
end
+luamplib.colorconverter = colorconverter
--
-- End of File `luamplib.lua'.