summaryrefslogtreecommitdiff
path: root/tex
diff options
context:
space:
mode:
authorHans Hagen <pragma@wxs.nl>2019-04-04 14:11:01 +0200
committerContext Git Mirror Bot <phg@phi-gamma.net>2019-04-04 14:11:01 +0200
commit64f6e8fc0c6cb9254a6fe3db0b4ab31c51cf8524 (patch)
tree1b36a0b35f5b6d516d27fe817a27249d4c6d9c78 /tex
parent70a938c4934f042face9805fc4c392c0676b11d5 (diff)
downloadcontext-64f6e8fc0c6cb9254a6fe3db0b4ab31c51cf8524.tar.gz
2019-04-04 13:38:00
Diffstat (limited to 'tex')
-rw-r--r--tex/context/base/mkii/cont-new.mkii2
-rw-r--r--tex/context/base/mkii/context.mkii2
-rw-r--r--tex/context/base/mkii/mult-de.mkii1
-rw-r--r--tex/context/base/mkii/mult-en.mkii1
-rw-r--r--tex/context/base/mkii/mult-nl.mkii1
-rw-r--r--tex/context/base/mkiv/anch-pgr.lua120
-rw-r--r--tex/context/base/mkiv/anch-pos.lua128
-rw-r--r--tex/context/base/mkiv/attr-col.lua8
-rw-r--r--tex/context/base/mkiv/attr-ini.lua3
-rw-r--r--tex/context/base/mkiv/back-ini.lua12
-rw-r--r--tex/context/base/mkiv/back-lpd.lua2468
-rw-r--r--tex/context/base/mkiv/back-lua.lua52
-rw-r--r--tex/context/base/mkiv/back-mps.lua94
-rw-r--r--tex/context/base/mkiv/back-out.lua291
-rw-r--r--tex/context/base/mkiv/back-out.mkiv23
-rw-r--r--tex/context/base/mkiv/back-pdf.lua11
-rw-r--r--tex/context/base/mkiv/buff-ini.lua13
-rw-r--r--tex/context/base/mkiv/buff-ver.lua63
-rw-r--r--tex/context/base/mkiv/char-ini.lua6
-rw-r--r--tex/context/base/mkiv/char-ini.mkiv32
-rw-r--r--tex/context/base/mkiv/char-tex.lua15
-rw-r--r--tex/context/base/mkiv/char-utf.lua13
-rw-r--r--tex/context/base/mkiv/cldf-bas.lua26
-rw-r--r--tex/context/base/mkiv/cldf-ini.lua14
-rw-r--r--tex/context/base/mkiv/cldf-int.lua5
-rw-r--r--tex/context/base/mkiv/colo-ini.lua27
-rw-r--r--tex/context/base/mkiv/cont-new.mkiv8
-rw-r--r--tex/context/base/mkiv/cont-run.mkiv4
-rw-r--r--tex/context/base/mkiv/context.mkiv10
-rw-r--r--tex/context/base/mkiv/core-dat.lua7
-rw-r--r--tex/context/base/mkiv/core-lmt.mkiv2
-rw-r--r--tex/context/base/mkiv/core-sys.lua4
-rw-r--r--tex/context/base/mkiv/data-aux.lua2
-rw-r--r--tex/context/base/mkiv/data-exp.lua6
-rw-r--r--tex/context/base/mkiv/data-tmp.lua6
-rw-r--r--tex/context/base/mkiv/data-zip.lua99
-rw-r--r--tex/context/base/mkiv/driv-ini.lua18
-rw-r--r--tex/context/base/mkiv/driv-shp.lua1388
-rw-r--r--tex/context/base/mkiv/driv-shp.mkiv28
-rw-r--r--tex/context/base/mkiv/font-cff.lua3
-rw-r--r--tex/context/base/mkiv/font-cft.lua1
-rw-r--r--tex/context/base/mkiv/font-con.lua57
-rw-r--r--tex/context/base/mkiv/font-ctx.lua6
-rw-r--r--tex/context/base/mkiv/font-dsp.lua11
-rw-r--r--tex/context/base/mkiv/font-fbk.lua12
-rw-r--r--tex/context/base/mkiv/font-fil.mkvi32
-rw-r--r--tex/context/base/mkiv/font-imp-quality.lua13
-rw-r--r--tex/context/base/mkiv/font-lib.mkvi1
-rw-r--r--tex/context/base/mkiv/font-map.lua3
-rw-r--r--tex/context/base/mkiv/font-mps.lua23
-rw-r--r--tex/context/base/mkiv/font-nod.lua6
-rw-r--r--tex/context/base/mkiv/font-one.lua16
-rw-r--r--tex/context/base/mkiv/font-osd.lua6
-rw-r--r--tex/context/base/mkiv/font-ota.lua6
-rw-r--r--tex/context/base/mkiv/font-otc.lua3
-rw-r--r--tex/context/base/mkiv/font-otj.lua3
-rw-r--r--tex/context/base/mkiv/font-otl.lua1
-rw-r--r--tex/context/base/mkiv/font-oto.lua17
-rw-r--r--tex/context/base/mkiv/font-otr.lua1
-rw-r--r--tex/context/base/mkiv/font-ots.lua12
-rw-r--r--tex/context/base/mkiv/font-oup.lua4
-rw-r--r--tex/context/base/mkiv/font-shp.lua9
-rw-r--r--tex/context/base/mkiv/font-sol.lua28
-rw-r--r--tex/context/base/mkiv/font-syn.lua24
-rw-r--r--tex/context/base/mkiv/font-tpk.lua1292
-rw-r--r--tex/context/base/mkiv/font-ttf.lua65
-rw-r--r--tex/context/base/mkiv/font-vir.lua15
-rw-r--r--tex/context/base/mkiv/grph-bmp.lua85
-rw-r--r--tex/context/base/mkiv/grph-chk.lua276
-rw-r--r--tex/context/base/mkiv/grph-img.lua748
-rw-r--r--tex/context/base/mkiv/grph-inc.lua68
-rw-r--r--tex/context/base/mkiv/grph-inc.mkiv2
-rw-r--r--tex/context/base/mkiv/l-bit32.lua10
-rw-r--r--tex/context/base/mkiv/l-dir.lua31
-rw-r--r--tex/context/base/mkiv/l-file.lua77
-rw-r--r--tex/context/base/mkiv/l-lua.lua13
-rw-r--r--tex/context/base/mkiv/l-os.lua21
-rw-r--r--tex/context/base/mkiv/l-table.lua104
-rw-r--r--tex/context/base/mkiv/lang-dis.lua1
-rw-r--r--tex/context/base/mkiv/lang-txt.lua14
-rw-r--r--tex/context/base/mkiv/lpdf-ano.lua61
-rw-r--r--tex/context/base/mkiv/lpdf-col.lua21
-rw-r--r--tex/context/base/mkiv/lpdf-emb.lua1839
-rw-r--r--tex/context/base/mkiv/lpdf-epa.lua6
-rw-r--r--tex/context/base/mkiv/lpdf-img.lua1206
-rw-r--r--tex/context/base/mkiv/lpdf-ini.lua347
-rw-r--r--tex/context/base/mkiv/lpdf-mis.lua4
-rw-r--r--tex/context/base/mkiv/lpdf-nod.lua2
-rw-r--r--tex/context/base/mkiv/lpdf-pde.lua14
-rw-r--r--tex/context/base/mkiv/lpdf-wid.lua25
-rw-r--r--tex/context/base/mkiv/luat-bas.mkiv1
-rw-r--r--tex/context/base/mkiv/luat-cnf.lua8
-rw-r--r--tex/context/base/mkiv/luat-cod.lua12
-rw-r--r--tex/context/base/mkiv/luat-fmt.lua16
-rw-r--r--tex/context/base/mkiv/luat-ini.lua2
-rw-r--r--tex/context/base/mkiv/luat-lib.mkiv4
-rw-r--r--tex/context/base/mkiv/luat-run.lua36
-rw-r--r--tex/context/base/mkiv/lxml-aux.lua25
-rw-r--r--tex/context/base/mkiv/lxml-inf.lua3
-rw-r--r--tex/context/base/mkiv/lxml-lpt.lua115
-rw-r--r--tex/context/base/mkiv/math-ali.mkiv7
-rw-r--r--tex/context/base/mkiv/math-dim.lua3
-rw-r--r--tex/context/base/mkiv/math-fbk.lua3
-rw-r--r--tex/context/base/mkiv/math-fen.mkiv42
-rw-r--r--tex/context/base/mkiv/math-ini.lua3
-rw-r--r--tex/context/base/mkiv/math-ini.mkiv16
-rw-r--r--tex/context/base/mkiv/math-noa.lua13
-rw-r--r--tex/context/base/mkiv/math-vfu.lua84
-rw-r--r--tex/context/base/mkiv/meta-fnt.lua8
-rw-r--r--tex/context/base/mkiv/meta-pdf.lua45
-rw-r--r--tex/context/base/mkiv/mlib-lua.lua31
-rw-r--r--tex/context/base/mkiv/mlib-pdf.lua53
-rw-r--r--tex/context/base/mkiv/mlib-pps.lua87
-rw-r--r--tex/context/base/mkiv/mlib-run.lua12
-rw-r--r--tex/context/base/mkiv/mtx-context-listing.tex8
-rw-r--r--tex/context/base/mkiv/mult-fun.lua2
-rw-r--r--tex/context/base/mkiv/mult-sys.mkiv52
-rw-r--r--tex/context/base/mkiv/node-fnt.lua3
-rw-r--r--tex/context/base/mkiv/node-ini.lua2
-rw-r--r--tex/context/base/mkiv/node-met.lua163
-rw-r--r--tex/context/base/mkiv/node-nut.lua9
-rw-r--r--tex/context/base/mkiv/node-pro.lua23
-rw-r--r--tex/context/base/mkiv/node-ref.lua12
-rw-r--r--tex/context/base/mkiv/node-res.lua35
-rw-r--r--tex/context/base/mkiv/node-rul.lua32
-rw-r--r--tex/context/base/mkiv/node-tsk.lua7
-rw-r--r--tex/context/base/mkiv/pack-obj.lua21
-rw-r--r--tex/context/base/mkiv/page-ini.mkiv4
-rw-r--r--tex/context/base/mkiv/page-lin.lua11
-rw-r--r--tex/context/base/mkiv/page-sid.mkiv38
-rw-r--r--tex/context/base/mkiv/publ-aut.lua32
-rw-r--r--tex/context/base/mkiv/publ-imp-apa.mkvi24
-rw-r--r--tex/context/base/mkiv/publ-imp-aps.mkvi20
-rw-r--r--tex/context/base/mkiv/publ-imp-commands.mkvi2
-rw-r--r--tex/context/base/mkiv/publ-imp-default.mkvi22
-rw-r--r--tex/context/base/mkiv/publ-ini.lua18
-rw-r--r--tex/context/base/mkiv/scrn-wid.lua2
-rw-r--r--tex/context/base/mkiv/scrn-wid.mkvi3
-rw-r--r--tex/context/base/mkiv/scrp-ini.lua10
-rw-r--r--tex/context/base/mkiv/sort-ini.lua29
-rw-r--r--tex/context/base/mkiv/spac-hor.mkiv2
-rw-r--r--tex/context/base/mkiv/spac-prf.lua5
-rw-r--r--tex/context/base/mkiv/spac-ver.lua147
-rw-r--r--tex/context/base/mkiv/spac-ver.mkiv1
-rw-r--r--tex/context/base/mkiv/status-files.pdfbin26541 -> 26085 bytes
-rw-r--r--tex/context/base/mkiv/status-lua.pdfbin268377 -> 224613 bytes
-rw-r--r--tex/context/base/mkiv/strc-doc.lua28
-rw-r--r--tex/context/base/mkiv/strc-lst.lua24
-rw-r--r--tex/context/base/mkiv/strc-mar.lua11
-rw-r--r--tex/context/base/mkiv/strc-not.lua39
-rw-r--r--tex/context/base/mkiv/strc-num.lua27
-rw-r--r--tex/context/base/mkiv/strc-pag.lua16
-rw-r--r--tex/context/base/mkiv/strc-ref.lua16
-rw-r--r--tex/context/base/mkiv/strc-reg.lua53
-rw-r--r--tex/context/base/mkiv/strc-reg.mkiv26
-rw-r--r--tex/context/base/mkiv/strc-ren.mkiv6
-rw-r--r--tex/context/base/mkiv/supp-box.lua8
-rw-r--r--tex/context/base/mkiv/symb-ini.mkiv14
-rw-r--r--tex/context/base/mkiv/syst-ini.mkiv1
-rw-r--r--tex/context/base/mkiv/tabl-tbl.mkiv6
-rw-r--r--tex/context/base/mkiv/tabl-xtb.lua3
-rw-r--r--tex/context/base/mkiv/toks-ini.lua7
-rw-r--r--tex/context/base/mkiv/toks-scn.lua5
-rw-r--r--tex/context/base/mkiv/trac-deb.lua97
-rw-r--r--tex/context/base/mkiv/trac-exp.lua2
-rw-r--r--tex/context/base/mkiv/trac-inf.lua4
-rw-r--r--tex/context/base/mkiv/trac-lmx.lua3
-rw-r--r--tex/context/base/mkiv/trac-log.lua2
-rw-r--r--tex/context/base/mkiv/trac-vis.lua37
-rw-r--r--tex/context/base/mkiv/typo-brk.lua14
-rw-r--r--tex/context/base/mkiv/typo-lin.lua12
-rw-r--r--tex/context/base/mkiv/typo-mar.lua36
-rw-r--r--tex/context/base/mkiv/util-deb.lua10
-rw-r--r--tex/context/base/mkiv/util-env.lua12
-rw-r--r--tex/context/base/mkiv/util-fil.lua157
-rw-r--r--tex/context/base/mkiv/util-fmt.lua11
-rw-r--r--tex/context/base/mkiv/util-prs.lua87
-rw-r--r--tex/context/base/mkiv/util-sac.lua16
-rw-r--r--tex/context/base/mkiv/util-soc-imp-copas.lua10
-rw-r--r--tex/context/base/mkiv/util-soc-imp-mime.lua4
-rw-r--r--tex/context/base/mkiv/util-soc-imp-socket.lua2
-rw-r--r--tex/context/base/mkiv/util-str.lua41
-rw-r--r--tex/context/base/mkiv/util-tab.lua30
-rw-r--r--tex/context/base/mkiv/util-zip.lua549
-rw-r--r--tex/context/fonts/mkiv/type-imp-plex.mkiv336
-rw-r--r--tex/context/interface/mkii/keys-de.xml1
-rw-r--r--tex/context/interface/mkii/keys-en.xml1
-rw-r--r--tex/context/interface/mkii/keys-nl.xml1
-rw-r--r--tex/context/interface/mkiv/i-context.pdfbin865200 -> 902663 bytes
-rw-r--r--tex/context/interface/mkiv/i-readme.pdfbin61095 -> 24423 bytes
-rw-r--r--tex/context/modules/common/s-abbreviations-logos.tex33
-rw-r--r--tex/context/modules/mkiv/m-chart.lua4
-rw-r--r--tex/context/modules/mkiv/m-punk.mkiv8
-rw-r--r--tex/context/sample/third/aristotle-grc.tex13
-rw-r--r--tex/context/sample/third/capek-cz.tex13
-rw-r--r--tex/context/sample/third/capek-vlnka-cz.tex13
-rw-r--r--tex/context/sample/third/dequincey.tex5
-rw-r--r--tex/context/sample/third/dyrynk-cz.tex22
-rw-r--r--tex/context/sample/third/dyrynk-vlnka-cz.tex23
-rw-r--r--tex/context/sample/third/kollar-cz.tex31
-rw-r--r--tex/context/sample/third/kollar-vlnka-cz.tex30
-rw-r--r--tex/context/sample/third/komensky-cz.tex33
-rw-r--r--tex/context/sample/third/komensky-vlnka-cz.tex33
-rw-r--r--tex/context/sample/third/krdel-sk.tex7
-rw-r--r--tex/context/sample/third/kun-cz.tex7
-rw-r--r--tex/generic/context/luatex/luatex-basics-nod.lua140
-rw-r--r--tex/generic/context/luatex/luatex-fonts-merged.lua517
-rw-r--r--tex/generic/context/luatex/luatex-fonts.lua4
-rw-r--r--tex/generic/context/luatex/luatex-plain.tex2
209 files changed, 13841 insertions, 1888 deletions
diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii
index afb671bbd..0dda26e80 100644
--- a/tex/context/base/mkii/cont-new.mkii
+++ b/tex/context/base/mkii/cont-new.mkii
@@ -11,7 +11,7 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\newcontextversion{2019.02.14 16:57}
+\newcontextversion{2019.04.04 13:31}
%D This file is loaded at runtime, thereby providing an
%D excellent place for hacks, patches, extensions and new
diff --git a/tex/context/base/mkii/context.mkii b/tex/context/base/mkii/context.mkii
index f50ab529e..91d282601 100644
--- a/tex/context/base/mkii/context.mkii
+++ b/tex/context/base/mkii/context.mkii
@@ -20,7 +20,7 @@
%D your styles an modules.
\edef\contextformat {\jobname}
-\edef\contextversion{2019.02.14 16:57}
+\edef\contextversion{2019.04.04 13:31}
%D For those who want to use this:
diff --git a/tex/context/base/mkii/mult-de.mkii b/tex/context/base/mkii/mult-de.mkii
index 0a15a4f30..46a239304 100644
--- a/tex/context/base/mkii/mult-de.mkii
+++ b/tex/context/base/mkii/mult-de.mkii
@@ -587,6 +587,7 @@
\setinterfacevariable{understrike}{understrike}
\setinterfacevariable{understrikes}{understrikes}
\setinterfacevariable{unframed}{unframed}
+\setinterfacevariable{unicode}{unicode}
\setinterfacevariable{unit}{einheit}
\setinterfacevariable{units}{einheiten}
\setinterfacevariable{unknown}{unbekannt}
diff --git a/tex/context/base/mkii/mult-en.mkii b/tex/context/base/mkii/mult-en.mkii
index faf268576..0f9cc15e1 100644
--- a/tex/context/base/mkii/mult-en.mkii
+++ b/tex/context/base/mkii/mult-en.mkii
@@ -587,6 +587,7 @@
\setinterfacevariable{understrike}{understrike}
\setinterfacevariable{understrikes}{understrikes}
\setinterfacevariable{unframed}{unframed}
+\setinterfacevariable{unicode}{unicode}
\setinterfacevariable{unit}{unit}
\setinterfacevariable{units}{units}
\setinterfacevariable{unknown}{unknown}
diff --git a/tex/context/base/mkii/mult-nl.mkii b/tex/context/base/mkii/mult-nl.mkii
index 884503363..6376b158a 100644
--- a/tex/context/base/mkii/mult-nl.mkii
+++ b/tex/context/base/mkii/mult-nl.mkii
@@ -587,6 +587,7 @@
\setinterfacevariable{understrike}{understrike}
\setinterfacevariable{understrikes}{understrikes}
\setinterfacevariable{unframed}{unframed}
+\setinterfacevariable{unicode}{unicode}
\setinterfacevariable{unit}{eenheid}
\setinterfacevariable{units}{eenheden}
\setinterfacevariable{unknown}{onbekend}
diff --git a/tex/context/base/mkiv/anch-pgr.lua b/tex/context/base/mkiv/anch-pgr.lua
index 32b7c2960..14afa3967 100644
--- a/tex/context/base/mkiv/anch-pgr.lua
+++ b/tex/context/base/mkiv/anch-pgr.lua
@@ -94,7 +94,14 @@ local enabled = false
-- Freeing the data is somewhat tricky as we can have backgrounds spanning
-- many pages but for an arbitrary background shape that is not so common.
-local function check(a,index,depth,d,where,ht,dp)
+local function check(specification)
+ local a = specification.attribute
+ local index = specification.index
+ local depth = specification.depth
+ local d = specification.data
+ local where = specification.where
+ local ht = specification.ht
+ local dp = specification.dp
-- this is not yet r2l ready
local w = d.shapes[realpage]
local x, y = getpos()
@@ -107,7 +114,7 @@ local function check(a,index,depth,d,where,ht,dp)
n = n + 1
d.index = index
d.depth = depth
--- w[n] = { x, x, y, ht, dp }
+ -- w[n] = { x, x, y, ht, dp }
w[n] = { y, ht, dp, x, x }
else
local wn = w[n]
@@ -148,8 +155,8 @@ local function flush(head,f,l,a,parent,depth)
local ix = index
local ht = getheight(parent)
local dp = getdepth(parent)
- local ln = new_latelua(function() check(a,ix,depth,d,"l",ht,dp) end)
- local rn = new_latelua(function() check(a,ix,depth,d,"r",ht,dp) end)
+ local ln = new_latelua { action = check, attribute = a, index = ix, depth = depth, data = d, where = "l", ht = ht, dp = dp }
+ local rn = new_latelua { action = check, attribute = a, index = ix, depth = depth, data = d, where = "r", ht = ht, dp = dp }
if trace_ranges then
ln = new_hlist(setlink(new_rule(65536,65536*4,0),new_kern(-65536),ln))
rn = new_hlist(setlink(new_rule(65536,0,65536*4),new_kern(-65536),rn))
@@ -507,7 +514,8 @@ local function shape(kind,b,p,realpage,xmin,xmax,ymin,ymax,fh,ld)
-- use height of b and depth of e, maybe check for weird border
-- cases here
if fh then
- local lsf, rsf = ls[1], rs[1]
+ local lsf = ls[1]
+ local rsf = rs[1]
if lsf[2] < fh then
lsf[2] = fh
end
@@ -516,7 +524,8 @@ local function shape(kind,b,p,realpage,xmin,xmax,ymin,ymax,fh,ld)
end
end
if fd then
- local lsl, rsl = ls[n], rs[n]
+ local lsl = ls[n]
+ local rsl = rs[n]
if lsl[2] > fd then
lsl[2] = fd
end
@@ -533,12 +542,18 @@ local function shape(kind,b,p,realpage,xmin,xmax,ymin,ymax,fh,ld)
end
local function singlepart(b,e,p,realpage,r,left,right)
- local bx, by = b.x, b.y
- local ex, ey = e.x, e.y
- local rx, ry = r.x, r.y
- local bh, bd = by + b.h, by - b.d
- local eh, ed = ey + e.h, ey - e.d
- local rh, rd = ry + r.h, ry - r.d
+ local bx = b.x
+ local by = b.y
+ local ex = e.x
+ local ey = e.y
+ local rx = r.x
+ local ry = r.y
+ local bh = by + b.h
+ local bd = by - b.d
+ local eh = ey + e.h
+ local ed = ey - e.d
+ local rh = ry + r.h
+ local rd = ry - r.d
local rw = rx + r.w
if left then
rx = rx + left
@@ -591,10 +606,14 @@ local function singlepart(b,e,p,realpage,r,left,right)
end
local function firstpart(b,e,p,realpage,r,left,right)
- local bx, by = b.x, b.y
- local rx, ry = r.x, r.y
- local bh, bd = by + b.h, by - b.d
- local rh, rd = ry + r.h, ry - r.d
+ local bx = b.x
+ local by = b.y
+ local rx = r.x
+ local ry = r.y
+ local bh = by + b.h
+ local bd = by - b.d
+ local rh = ry + r.h
+ local rd = ry - r.d
local rw = rx + r.w
if left then
rx = rx + left
@@ -628,8 +647,10 @@ local function firstpart(b,e,p,realpage,r,left,right)
end
local function middlepart(b,e,p,realpage,r,left,right)
- local rx, ry = r.x, r.y
- local rh, rd = ry + r.h, ry - r.d
+ local rx = r.x
+ local ry = r.y
+ local rh = ry + r.h
+ local rd = ry - r.d
local rw = rx + r.w
if left then
rx = rx + left
@@ -652,10 +673,14 @@ local function middlepart(b,e,p,realpage,r,left,right)
end
local function lastpart(b,e,p,realpage,r,left,right)
- local ex, ey = e.x, e.y
- local rx, ry = r.x, r.y
- local eh, ed = ey + e.h, ey - e.d
- local rh, rd = ry + r.h, ry - r.d
+ local ex = e.x
+ local ey = e.y
+ local rx = r.x
+ local ry = r.y
+ local eh = ey + e.h
+ local ed = ey - e.d
+ local rh = ry + r.h
+ local rd = ry - r.d
local rw = rx + r.w
if left then
rx = rx + left
@@ -842,8 +867,10 @@ local function freemultipar(pagedata,frees) -- ,k
local areas = { }
data.areas = areas
- local f_1, n_1 = { }, 0
- local f_2, n_2 = { }, 0
+ local f_1 = { }
+ local n_1 = 0
+ local f_2 = { }
+ local n_2 = 0
for i=1,#frees do
local f = frees[i]
local k = f.k
@@ -906,14 +933,18 @@ local function freemultipar(pagedata,frees) -- ,k
-- we can collect the coordinates first
local function check_two(area,frees)
- local ul = area[1]
- local ur = area[2]
- local lr = area[3]
- local ll = area[4]
- local ulx, uly = ul[1], ul[2]
- local urx, ury = ur[1], ur[2]
- local lrx, lry = lr[1], lr[2]
- local llx, lly = ll[1], ll[2]
+ local ul = area[1]
+ local ur = area[2]
+ local lr = area[3]
+ local ll = area[4]
+ local ulx = ul[1]
+ local uly = ul[2]
+ local urx = ur[1]
+ local ury = ur[2]
+ local lrx = lr[1]
+ local lry = lr[2]
+ local llx = ll[1]
+ local lly = ll[2]
local temp = { }
local n = 0
@@ -1106,12 +1137,16 @@ local function fetchmultipar(n,anchor,page)
report_graphics("fetching %a at page %s using anchor %a containing %s multipars",
n,page,anchor,nofmultipars)
end
- local x, y = a.x, a.y
- local w, h, d = a.w, a.h, a.d
- local bpos = data.bpos
- local bh, bd = bpos.h, bpos.d
- local result = { false } -- slot 1 will be set later
- local n = 0
+ local x = a.x
+ local y = a.y
+ local w = a.w
+ local h = a.h
+ local d = a.d
+ local bpos = data.bpos
+ local bh = bpos.h
+ local bd = bpos.d
+ local result = { false } -- slot 1 will be set later
+ local n = 0
for i=1,nofmultipars do
local data = pagedata[i]
local location = data.location
@@ -1176,7 +1211,8 @@ implement {
if type(tags) == "string" then
tags = utilities.parsers.settings_to_array(tags)
end
- local list, nofboxes = { }, 0
+ local list = { }
+ local nofboxes = 0
for i=1,#tags do
local tag= tags[i]
local c = collected[tag]
@@ -1185,7 +1221,11 @@ implement {
if r then
r = collected[r]
if r then
- local rx, ry, rw, rh, rd = r.x, r.y, r.w, r.h, r.d
+ local rx = r.x
+ local ry = r.y
+ local rw = r.w
+ local rh = r.h
+ local rd = r.d
local cx = c.x - rx
local cy = c.y
local cw = cx + c.w
diff --git a/tex/context/base/mkiv/anch-pos.lua b/tex/context/base/mkiv/anch-pos.lua
index 9438fa2a7..56250e16d 100644
--- a/tex/context/base/mkiv/anch-pos.lua
+++ b/tex/context/base/mkiv/anch-pos.lua
@@ -44,7 +44,6 @@ local scanners = interfaces.scanners
local commands = commands
local context = context
-local ctxnode = context.nodes.flush
local ctx_latelua = context.latelua
@@ -75,7 +74,6 @@ local find_tail = nuts.tail
local hpack = nuts.hpack
local new_latelua = nuts.pool.latelua
-local new_latelua_node = nodes.pool.latelua
local variables = interfaces.variables
local v_text = variables.text
@@ -243,7 +241,6 @@ end
-- t[#t+1] = data
-- end
--
--- --
-- local pages = structures.pages.collected
-- if pages then
-- local last = nil
@@ -403,9 +400,29 @@ end
-- analyze some files (with lots if margindata) and then when one key optionally
-- use that one instead of a table (so, a 3rd / 4th argument: key, e.g. "x")
-local function set(name,index,val) -- ,key
- local data = enhance(val or index)
- if val then
+local function set(name,index,value) -- ,key
+ -- officially there should have been a settobesaved
+ local data = enhance(value or {})
+ if value then
+ container = tobesaved[name]
+ if not container then
+ tobesaved[name] = {
+ [index] = data
+ }
+ else
+ container[index] = data
+ end
+ else
+ tobesaved[name] = data
+ end
+end
+
+local function setspec(specification)
+ local name = specification.name
+ local index = specification.index
+ local value = specification.value
+ local data = enhance(value or {})
+ if value then
container = tobesaved[name]
if not container then
tobesaved[name] = {
@@ -428,16 +445,11 @@ local function get(id,index)
end
end
-------------.setdim = setdim
-jobpositions.setall = setall
-jobpositions.set = set
-jobpositions.get = get
-
--- scanners.setpos = setall
-
--- trackers.enable("tokens.compi*")
-
--- something weird: the compiler fails us here
+------------.setdim = setdim
+jobpositions.setall = setall
+jobpositions.set = set
+jobpositions.setspec = setspec
+jobpositions.get = get
scanners.dosaveposition = compilescanner {
actions = setall, -- name p x y
@@ -459,7 +471,8 @@ scanners.dosavepositionplus = compilescanner {
-- not much gain in keeping stack (inc/dec instead of insert/remove)
-local function b_column(tag)
+local function b_column(specification)
+ local tag = specification.tag
local x = gethpos()
tobesaved[tag] = {
r = true,
@@ -470,7 +483,7 @@ local function b_column(tag)
column = tag
end
-local function e_column(tag)
+local function e_column()
local t = tobesaved[column]
if not t then
-- something's wrong
@@ -496,8 +509,7 @@ scanners.bposcolumnregistered = function() -- tag
local tag = scanstring()
insert(columns,tag)
column = tag
--- ctxnode(new_latelua_node(function() b_column(tag) end))
- ctx_latelua(function() b_column(tag) end)
+ ctx_latelua { action = b_column, tag = tag }
end
scanners.eposcolumn = function()
@@ -506,15 +518,15 @@ scanners.eposcolumn = function()
end
scanners.eposcolumnregistered = function()
--- ctxnode(new_latelua_node(e_column))
- ctx_latelua(e_column)
+ ctx_latelua { action = e_column }
remove(columns)
column = columns[#columns]
end
-- regions
-local function b_region(tag)
+local function b_region(specification)
+ local tag = specification.tag or specification
local last = tobesaved[tag]
local x, y = getpos()
last.x = x ~= 0 and x or nil
@@ -524,11 +536,11 @@ local function b_region(tag)
region = tag
end
-local function e_region(correct)
+local function e_region(specification)
local last = tobesaved[region]
local y = getvpos()
local x, y = getpos()
- if correct then
+ if specification.correct then
local h = (last.y or 0) - y
last.h = h ~= 0 and h or nil
end
@@ -569,8 +581,8 @@ end
local function markregionbox(n,tag,correct,...) -- correct needs checking
local tag, box = setregionbox(n,tag,...)
-- todo: check if tostring is needed with formatter
- local push = new_latelua(function() b_region(tag) end)
- local pop = new_latelua(function() e_region(correct) end)
+ local push = new_latelua { action = b_region, tag = tag }
+ local pop = new_latelua { action = e_region, correct = correct }
-- maybe we should construct a hbox first (needs experimenting) so that we can avoid some at the tex end
local head = getlist(box)
-- no, this fails with \framed[region=...] .. needs thinking
@@ -604,6 +616,13 @@ function jobpositions.gettobesaved(name,tag)
end
end
+function jobpositions.settobesaved(name,tag,data)
+ local t = tobesaved[name]
+ if t and tag and data then
+ t[tag] = data
+ end
+end
+
local nofparagraphs = 0
scanners.parpos = function()
@@ -645,15 +664,14 @@ scanners.parpos = function()
if parshape and #parshape > 0 then
t.ps = parshape
end
- local tag = f_p_tag(nofparagraphs)
- tobesaved[tag] = t
--- ctxnode(new_latelua_node(function() enhance(tobesaved[tag]) end))
- ctx_latelua(function() enhance(tobesaved[tag]) end)
+ local name = f_p_tag(nofparagraphs)
+ tobesaved[name] = t
+ ctx_latelua { action = enhance, specification = t }
end
scanners.dosetposition = function() -- name
local name = scanstring()
- tobesaved[name] = {
+ local spec = {
p = true,
c = column,
r = true,
@@ -662,16 +680,16 @@ scanners.dosetposition = function() -- name
n = nofparagraphs > 0 and nofparagraphs or nil,
r2l = texgetcount("inlinelefttoright") == 1 or nil,
}
--- ctxnode(new_latelua_node(function() enhance(tobesaved[name]) end))
- ctx_latelua(function() enhance(tobesaved[name]) end)
+ tobesaved[name] = spec
+ ctx_latelua { action = enhance, specification = spec }
end
scanners.dosetpositionwhd = function() -- name w h d extra
local name = scanstring()
- local w = scandimen()
- local h = scandimen()
- local d = scandimen()
- tobesaved[name] = {
+ local w = scandimen()
+ local h = scandimen()
+ local d = scandimen()
+ local spec = {
p = true,
c = column,
r = true,
@@ -683,15 +701,15 @@ scanners.dosetpositionwhd = function() -- name w h d extra
n = nofparagraphs > 0 and nofparagraphs or nil,
r2l = texgetcount("inlinelefttoright") == 1 or nil,
}
--- ctxnode(new_latelua_node(function() enhance(tobesaved[name]) end))
- ctx_latelua(function() enhance(tobesaved[name]) end)
+ tobesaved[name] = spec
+ ctx_latelua { action = enhance, specification = spec }
end
scanners.dosetpositionbox = function() -- name box
local name = scanstring()
local box = getbox(scaninteger())
local w, h, d = getwhd(box)
- tobesaved[name] = {
+ local spec = {
p = true,
c = column,
r = true,
@@ -703,16 +721,16 @@ scanners.dosetpositionbox = function() -- name box
n = nofparagraphs > 0 and nofparagraphs or nil,
r2l = texgetcount("inlinelefttoright") == 1 or nil,
}
--- ctxnode(new_latelua_node(function() enhance(tobesaved[name]) end))
- ctx_latelua(function() enhance(tobesaved[name]) end)
+ tobesaved[name] = spec
+ ctx_latelua { action = enhance, specification = spec }
end
scanners.dosetpositionplus = function() -- name w h d extra
local name = scanstring()
- local w = scandimen()
- local h = scandimen()
- local d = scandimen()
- tobesaved[name] = {
+ local w = scandimen()
+ local h = scandimen()
+ local d = scandimen()
+ local spec = {
p = true,
c = column,
r = true,
@@ -725,15 +743,15 @@ scanners.dosetpositionplus = function() -- name w h d extra
e = scanstring(),
r2l = texgetcount("inlinelefttoright") == 1 or nil,
}
--- ctxnode(new_latelua_node(function() enhance(tobesaved[name]) end))
- ctx_latelua(function() enhance(tobesaved[name]) end)
+ tobesaved[name] = spec
+ ctx_latelua { action = enhance, specification = spec }
end
scanners.dosetpositionstrut = function() -- name
local name = scanstring()
local box = getbox("strutbox")
local w, h, d = getwhd(box)
- tobesaved[name] = {
+ local spec = {
p = true,
c = column,
r = true,
@@ -744,8 +762,8 @@ scanners.dosetpositionstrut = function() -- name
n = nofparagraphs > 0 and nofparagraphs or nil,
r2l = texgetcount("inlinelefttoright") == 1 or nil,
}
--- ctxnode(new_latelua_node(function() enhance(tobesaved[name]) end))
- ctx_latelua(function() enhance(tobesaved[name]) end)
+ tobesaved[name] = spec
+ ctx_latelua { action = enhance, specification = spec }
end
scanners.dosetpositionstrutkind = function() -- name
@@ -753,7 +771,7 @@ scanners.dosetpositionstrutkind = function() -- name
local kind = scaninteger()
local box = getbox("strutbox")
local w, h, d = getwhd(box)
- tobesaved[name] = {
+ local spec = {
k = kind,
p = true,
c = column,
@@ -765,8 +783,8 @@ scanners.dosetpositionstrutkind = function() -- name
n = nofparagraphs > 0 and nofparagraphs or nil,
r2l = texgetcount("inlinelefttoright") == 1 or nil,
}
--- ctxnode(new_latelua_node(function() enhance(tobesaved[name]) end))
- ctx_latelua(function() enhance(tobesaved[name]) end)
+ tobesaved[name] = spec
+ ctx_latelua { action = enhance, specification = spec }
end
function jobpositions.getreserved(tag,n)
diff --git a/tex/context/base/mkiv/attr-col.lua b/tex/context/base/mkiv/attr-col.lua
index 2d4b65181..5ea72c7e3 100644
--- a/tex/context/base/mkiv/attr-col.lua
+++ b/tex/context/base/mkiv/attr-col.lua
@@ -368,10 +368,14 @@ local function reviver(data,n)
local gray = graycolor(v[2])
d = { gray, gray, gray, gray }
elseif model == 3 then
- local gray, rgb, cmyk = graycolor(v[2]), rgbcolor(v[3],v[4],v[5]), cmykcolor(v[6],v[7],v[8],v[9])
+ local gray = graycolor(v[2])
+ local rgb = rgbcolor(v[3],v[4],v[5])
+ local cmyk = cmykcolor(v[6],v[7],v[8],v[9])
d = { rgb, gray, rgb, cmyk }
elseif model == 4 then
- local gray, rgb, cmyk = graycolor(v[2]), rgbcolor(v[3],v[4],v[5]), cmykcolor(v[6],v[7],v[8],v[9])
+ local gray = graycolor(v[2])
+ local rgb = rgbcolor(v[3],v[4],v[5])
+ local cmyk = cmykcolor(v[6],v[7],v[8],v[9])
d = { cmyk, gray, rgb, cmyk }
elseif model == 5 then
local spot = spotcolor(v[10],v[11],v[12],v[13])
diff --git a/tex/context/base/mkiv/attr-ini.lua b/tex/context/base/mkiv/attr-ini.lua
index 63015d205..dd971afc1 100644
--- a/tex/context/base/mkiv/attr-ini.lua
+++ b/tex/context/base/mkiv/attr-ini.lua
@@ -114,7 +114,8 @@ local function showlist(what,list)
local a = list.next
local i = 0
while a do
- local number, value = a.number, a.value
+ local number = a.number
+ local value = a.value
i = i + 1
report_attribute("%S %2i: attribute %3i, value %4i, name %a",what,i,number,value,names[number])
a = a.next
diff --git a/tex/context/base/mkiv/back-ini.lua b/tex/context/base/mkiv/back-ini.lua
index 94cdcd29f..b7af1529b 100644
--- a/tex/context/base/mkiv/back-ini.lua
+++ b/tex/context/base/mkiv/back-ini.lua
@@ -76,7 +76,7 @@ local lmtx_mode = nil
local function lmtxmode()
if lmtx_mode == nil then
- lmtx_mode = environment.lmtxmode and drivers and drivers.lmtxversion
+ lmtx_mode = ((tonumber(CONTEXTLMTXMODE) or 0) > 0) and drivers and drivers.lmtxversion
end
return lmtx_mode
end
@@ -208,11 +208,11 @@ local savenode = nodepool.save
local restorenode = nodepool.restore
local setmatrixnode = nodepool.setmatrix
--- updaters.register("backend.update",function()
--- savenode = nodepool.save
--- restorenode = nodepool.restore
--- setmatrixnode = nodepool.setmatrix
--- end)
+updaters.register("backend.update",function()
+ savenode = nodepool.save
+ restorenode = nodepool.restore
+ setmatrixnode = nodepool.setmatrix
+end)
local function stopsomething()
local top = remove(stack)
diff --git a/tex/context/base/mkiv/back-lpd.lua b/tex/context/base/mkiv/back-lpd.lua
new file mode 100644
index 000000000..44ffbc43a
--- /dev/null
+++ b/tex/context/base/mkiv/back-lpd.lua
@@ -0,0 +1,2468 @@
+if not modules then modules = { } end modules ['back-lpd'] = {
+ version = 1.001,
+ comment = "companion to lpdf-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- If you consider this complex, watch:
+--
+-- https://www.youtube.com/watch?v=6H-cAzfB2qo
+--
+-- or in distactionmode:
+--
+-- https://www.youtube.com/watch?v=TYuTE_1jvvE
+-- https://www.youtube.com/watch?v=nnicGKX3lvM
+--
+-- For the moment we have to support the built in backend as well as the alternative. So the
+-- next interface is suboptimal and will change at some time.
+
+local type, next, unpack, tonumber = type, next, unpack, tonumber
+local char, rep, find = string.char, string.rep, string.find
+local formatters, splitstring = string.formatters, string.split
+local band, extract = bit32.band, bit32.extract
+local concat, keys, sortedhash = table.concat, table.keys, table.sortedhash
+local setmetatableindex = table.setmetatableindex
+
+local bpfactor = number.dimenfactors.bp
+
+local md5HEX = md5.HEX
+local osuuid = os.uuid
+local zlibcompress = flate.zip_compress or zlib.compress
+
+local starttiming = statistics.starttiming
+local stoptiming = statistics.stoptiming
+
+local nuts = nodes.nuts
+local tonut = nodes.tonut
+
+local getdata = nuts.getdata
+local getsubtype = nuts.getsubtype
+local getfield = nuts.getfield
+local getwhd = nuts.getwhd
+local flushlist = nuts.flush_list
+
+local pdfincludeimage = lpdf.includeimage
+local pdfgetfontname = lpdf.getfontname
+local pdfgetfontobjnumber = lpdf.getfontobjnumber
+
+local pdfreserveobject = lpdf.reserveobject
+local pdfpagereference = lpdf.pagereference
+local pdfflushobject = lpdf.flushobject
+local pdfreference = lpdf.reference
+local pdfdictionary = lpdf.dictionary
+local pdfarray = lpdf.array
+local pdfconstant = lpdf.constant
+local pdfflushstreamobject = lpdf.flushstreamobject
+local pdfliteral = lpdf.literal -- not to be confused with a whatsit!
+
+local pdf_pages = pdfconstant("Pages")
+local pdf_page = pdfconstant("Page")
+local pdf_xobject = pdfconstant("XObject")
+local pdf_form = pdfconstant("Form")
+
+local fonthashes = fonts.hashes
+local characters = fonthashes.characters
+local parameters = fonthashes.parameters
+local properties = fonthashes.properties
+
+local report = logs.reporter("backend")
+
+do
+
+ local dummy = function() end
+
+ local function unavailable(t,k)
+ report("calling unavailable pdf.%s function",k)
+ t[k] = dummy
+ return dummy
+ end
+
+ updaters.register("backend.update.pdf",function()
+ setmetatableindex(pdf,unavailable)
+ end)
+
+ updaters.register("backend.update",function()
+ pdf = setmetatableindex(unavailable)
+ end)
+
+end
+
+-- used variables
+
+local pdf_h, pdf_v
+local need_tm, need_tf, cur_tmrx, cur_factor, cur_f, cur_e
+local need_width, need_mode, done_width, done_mode
+local mode
+local f_pdf_cur, f_pdf, fs_cur, fs, f_cur
+local tj_delta, cw
+local usedfonts, usedxforms, usedximages
+local getxformname, getximagename
+local boundingbox, shippingmode, objectnumber
+local tmrx, tmry, tmsx, tmsy, tmtx, tmty
+local cmrx, cmry, cmsx, cmsy, cmtx, cmty
+
+local function usefont(t,k) -- a bit redundant hash
+ local v = pdfgetfontname(k)
+ t[k] = v
+ return v
+end
+
+local function reset_variables(specification)
+ pdf_h, pdf_v = 0, 0
+ cmrx, cmry = 1, 1
+ cmsx, cmsy = 0, 0
+ cmtx, cmty = 0, 0
+ tmrx, tmry = 1, 1
+ tmsx, tmsy = 0, 0
+ tmtx, tmty = 0, 0
+ need_tm = false
+ need_tf = false
+ need_width = 0
+ need_mode = 0
+ done_width = false
+ done_mode = false
+ mode = "page"
+ shippingmode = specification.shippingmode
+ objectnumber = specification.objectnumber
+ cur_tmrx = 0
+ f_cur = 0
+ f_pdf_cur = 0 -- nullfont
+ f_pdf = 0 -- nullfont
+ fs_cur = 0
+ fs = 0
+ tj_delta = 0
+ cur_factor = 0
+ cur_f = false
+ cur_e = false
+ cw = 0
+ usedfonts = setmetatableindex(usefont)
+ usedxforms = { }
+ usedximages = { }
+ boundingbox = specification.boundingbox
+ --
+-- if overload then
+-- overload()
+-- end
+end
+
+-- buffer
+
+local buffer = { }
+local b = 0
+
+local function reset_buffer()
+ -- buffer = { }
+ b = 0
+end
+
+local function flush_buffer()
+ b = 0
+end
+
+local function show_buffer()
+ print(concat(buffer,"\n",1,b))
+end
+
+-- fonts
+
+local fontcharacters
+local fontparameters
+local fontproperties
+local usedcharacters = setmetatableindex("table")
+local pdfcharacters
+local horizontalmode = true
+----- widefontmode = true
+local scalefactor = 1
+local minthreshold = -65536 * 5
+local maxthreshold = 65536 * 5
+local tjfactor = 100 / 65536
+
+lpdf.usedcharacters = usedcharacters
+
+local function updatefontstate(font)
+ fontcharacters = characters[font]
+ fontparameters = parameters[font]
+ fontproperties = properties[font]
+ local size = fontparameters.size -- or bad news
+ local designsize = fontparameters.designsize or size
+ pdfcharacters = usedcharacters[font]
+ horizontalmode = fontparameters.writingmode ~= "vertical"
+ -- widefontmode = fontproperties.encodingbytes == 2
+ scalefactor = (designsize/size) * tjfactor
+ maxthreshold = designsize
+ minthreshold = - maxthreshold
+end
+
+-- helpers
+
+local f_cm = formatters["%.6F %.6F %.6F %.6F %.6F %.6F cm"]
+local f_tm = formatters["%.6F %.6F %.6F %.6F %.6F %.6F Tm"]
+
+directives.register("pdf.stripzeros",function()
+ f_cm = formatters["%.6N %.6N %.6N %.6N %.6N %.6N cm"]
+ f_tm = formatters["%.6N %.6N %.6N %.6N %.6N %.6N Tm"]
+end)
+
+local saved_text_pos_v = 0
+local saved_text_pos_h = 0
+
+local function begin_text()
+ saved_text_pos_h = pdf_h
+ saved_text_pos_v = pdf_v
+ b = b + 1 ; buffer[b] = "BT"
+ need_tf = true
+ need_width = 0
+ need_mode = 0
+ mode = "text"
+end
+
+local function end_text()
+ if done_width then
+ b = b + 1 ; buffer[b] = "0 w"
+ done_width = false
+ end
+ if done_mode then
+ b = b + 1 ; buffer[b] = "0 Tr"
+ done_mode = false
+ end
+ b = b + 1 ; buffer[b] = "ET"
+ pdf_h = saved_text_pos_h
+ pdf_v = saved_text_pos_v
+ mode = "page"
+end
+
+local saved_chararray_pos_h
+local saved_chararray_pos_v
+
+local saved_b = 0
+
+local function begin_chararray()
+ saved_chararray_pos_h = pdf_h
+ saved_chararray_pos_v = pdf_v
+ cw = horizontalmode and saved_chararray_pos_h or - saved_chararray_pos_v
+ tj_delta = 0
+ saved_b = b
+ b = b + 1 ; buffer[b] = " ["
+ mode = "chararray"
+end
+
+local function end_chararray()
+ b = b + 1 ; buffer[b] = "] TJ"
+ buffer[saved_b] = concat(buffer,"",saved_b,b)
+ b = saved_b
+ pdf_h = saved_chararray_pos_h
+ pdf_v = saved_chararray_pos_v
+ mode = "text"
+end
+
+local function begin_charmode()
+ -- b = b + 1 ; buffer[b] = widefontmode and "<" or "("
+ b = b + 1 ; buffer[b] = "<"
+ mode = "char"
+end
+
+local function end_charmode()
+ -- b = b + 1 ; buffer[b] = widefontmode and ">" or ")"
+ b = b + 1 ; buffer[b] = ">"
+ mode = "chararray"
+end
+
+local function calc_pdfpos(h,v)
+ if mode == "page" then
+ cmtx = h - pdf_h
+ cmty = v - pdf_v
+ if h ~= pdf_h or v ~= pdf_v then
+ return true
+ end
+ elseif mode == "text" then
+ tmtx = h - saved_text_pos_h
+ tmty = v - saved_text_pos_v
+ if h ~= pdf_h or v ~= pdf_v then
+ return true
+ end
+ elseif horizontalmode then
+ tmty = v - saved_text_pos_v
+ tj_delta = cw - h -- + saved_chararray_pos_h
+ if tj_delta ~= 0 or v ~= pdf_v then
+ return true
+ end
+ else
+ tmtx = h - saved_text_pos_h
+ tj_delta = cw + v -- - saved_chararray_pos_v
+ if tj_delta ~= 0 or h ~= pdf_h then
+ return true
+ end
+ end
+ return false
+end
+
+local function pdf_set_pos(h,v)
+ local move = calc_pdfpos(h,v)
+ if move then
+ b = b + 1 ; buffer[b] = f_cm(cmrx, cmsx, cmsy, cmry, cmtx*bpfactor, cmty*bpfactor)
+ pdf_h = pdf_h + cmtx
+ pdf_v = pdf_v + cmty
+ end
+end
+
+local function pdf_reset_pos() -- pdf_set_pos(0,0)
+ if mode == "page" then
+ cmtx = - pdf_h
+ cmty = - pdf_v
+ if pdf_h == 0 and pdf_v == 0 then
+ return
+ end
+ elseif mode == "text" then
+ tmtx = - saved_text_pos_h
+ tmty = - saved_text_pos_v
+ if pdf_h == 0 and pdf_v == 0 then
+ return
+ end
+ elseif horizontalmode then
+ tmty = - saved_text_pos_v
+ tj_delta = cw
+ if tj_delta == 0 and pdf_v == 0 then
+ return
+ end
+ else
+ tmtx = - saved_text_pos_h
+ tj_delta = cw
+ if tj_delta == 0 and pdf_h == 0 then
+ return
+ end
+ end
+ b = b + 1 ; buffer[b] = f_cm(cmrx, cmsx, cmsy, cmry, cmtx*bpfactor, cmty*bpfactor)
+ pdf_h = pdf_h + cmtx
+ pdf_v = pdf_v + cmty
+end
+
+local function pdf_set_pos_temp(h,v)
+ local move = calc_pdfpos(h,v)
+ if move then
+ b = b + 1 ; buffer[b] = f_cm(cmrx, cmsx, cmsy, cmry, cmtx*bpfactor, cmty*bpfactor)
+ end
+end
+
+local function pdf_end_string_nl()
+ if mode == "char" then
+ end_charmode()
+ end_chararray()
+ elseif mode == "chararray" then
+ end_chararray()
+ end
+end
+
+local function pdf_goto_textmode()
+ if mode == "page" then
+ -- pdf_set_pos(0,0)
+ pdf_reset_pos()
+ begin_text()
+ elseif mode ~= "text" then
+ if mode == "char" then
+ end_charmode()
+ end_chararray()
+ else -- if mode == "chararray" then
+ end_chararray()
+ end
+ end
+end
+
+local function pdf_goto_pagemode()
+ if mode ~= "page" then
+ if mode == "char" then
+ end_charmode()
+ end_chararray()
+ end_text()
+ elseif mode == "chararray" then
+ end_chararray()
+ end_text()
+ elseif mode == "text" then
+ end_text()
+ end
+ end
+end
+
+local function pdf_goto_fontmode()
+ if mode == "char" then
+ end_charmode()
+ end_chararray()
+ end_text()
+ elseif mode == "chararray" then
+ end_chararray()
+ end_text()
+ elseif mode == "text" then
+ end_text()
+ end
+ -- pdf_set_pos(0,0)
+ pdf_reset_pos()
+ mode = "page"
+end
+
+-- characters
+
+local flushcharacter do
+
+ local round = math.round
+
+ local function setup_fontparameters(font,factor,f,e)
+ local slant = (fontparameters.slantfactor or 0) / 1000
+ local extend = (fontparameters.extendfactor or 1000) / 1000
+ local squeeze = (fontparameters.squeezefactor or 1000) / 1000
+ local expand = 1 + factor / 1000000
+ local format = fontproperties.format
+ if e then
+ extend = extend * e
+ end
+ tmrx = expand * extend
+ tmsy = slant
+ tmry = squeeze
+ need_width = fontparameters.width
+ need_mode = fontparameters.mode
+ f_cur = font
+ f_pdf = usedfonts[font] -- cache
+ cur_factor = factor
+ cur_f = f
+ cur_e = e
+ tj_delta = 0
+ fs = fontparameters.size * bpfactor
+ if f then
+ fs = fs * f
+ end
+ -- kind of special:
+ if format == "opentype" or format == "type1" then
+ fs = fs * 1000 / fontparameters.units -- can we avoid this ?
+ end
+ end
+
+ local f_width = formatters["%.6F w"]
+ local f_mode = formatters["%i Tr"]
+ local f_font = formatters["/F%i %.6F Tf"]
+ local s_width = "0 w"
+ local s_mode = "0 Tr"
+
+ directives.register("pdf.stripzeros",function()
+ f_width = formatters["%.6N w"]
+ f_font = formatters["/F%i %.6N Tf"]
+ end)
+
+ local function set_font()
+ if need_width and need_width ~= 0 then
+ b = b + 1 ; buffer[b] = f_width(bpfactor * need_width / 1000)
+ done_width = true
+ elseif done_width then
+ b = b + 1 ; buffer[b] = s_width
+ done_width = false
+ end
+ if need_mode and need_mode ~= 0 then
+ b = b + 1 ; buffer[b] = f_mode(need_mode)
+ done_mode = true
+ elseif done_mode then
+ b = b + 1 ; buffer[b] = s_mode
+ done_mode = false
+ end
+ b = b + 1 ; buffer[b] = f_font(f_pdf,fs)
+ f_pdf_cur = f_pdf
+ fs_cur = fs
+ need_tf = false
+ need_tm = true
+ end
+
+ local function set_textmatrix(h,v)
+ local move = calc_pdfpos(h,v) -- duplicate
+ if need_tm or move then
+ b = b + 1 ; buffer[b] = f_tm(tmrx, tmsx, tmsy, tmry, tmtx*bpfactor, tmty*bpfactor)
+ pdf_h = saved_text_pos_h + tmtx
+ pdf_v = saved_text_pos_v + tmty
+ need_tm = false
+ end
+ cur_tmrx = tmrx
+ end
+
+ -- local f_skip = formatters["%i"]
+ -- local f_octal = formatters["\\%o"]
+ -- local f_char = formatters["%c"]
+ local f_hex = formatters["%04X"]
+
+ local h_hex = setmetatableindex(function(t,k)
+ local v = f_hex(k)
+ t[k] = v
+ return v
+ end)
+
+ flushcharacter = function(current,pos_h,pos_v,pos_r,font,char,data,factor,width,f,e)
+ if need_tf or font ~= f_cur or f_pdf ~= f_pdf_cur or fs ~= fs_cur or mode == "page" then
+ pdf_goto_textmode()
+ setup_fontparameters(font,factor,f,e)
+ set_font()
+ elseif cur_tmrx ~= tmrx or cur_factor ~= factor or cur_f ~= f or cur_e ~= e then
+ setup_fontparameters(font,factor,f,e)
+ need_tm = true
+ end
+ local move = calc_pdfpos(pos_h,pos_v)
+ if move or need_tm then
+ if not need_tm then
+ if horizontalmode then
+ if (saved_text_pos_v + tmty) ~= pdf_v then
+ need_tm = true
+ elseif tj_delta >= maxthreshold or tj_delta <= minthreshold then
+ need_tm = true
+ end
+ else
+ if (saved_text_pos_h + tmtx) ~= pdf_h then
+ need_tm = true
+ elseif tj_delta >= maxthreshold or tj_delta <= minthreshold then
+ need_tm = true
+ end
+ end
+ end
+ if need_tm then
+ pdf_goto_textmode()
+ set_textmatrix(pos_h,pos_v)
+ begin_chararray()
+ move = calc_pdfpos(pos_h,pos_v)
+ end
+ if move then
+ -- local d = round(tj_delta * scalefactor)
+ -- if d ~= 0 then
+ local d = tj_delta * scalefactor
+ if d <= -0.5 or d >= 0.5 then
+ if mode == "char" then
+ end_charmode()
+ end
+ -- b = b + 1 ; buffer[b] = f_skip(d)
+ -- b = b + 1 ; buffer[b] = d
+ b = b + 1 ; buffer[b] = round(d)
+ end
+ cw = cw - tj_delta
+ end
+ end
+ if mode == "chararray" then
+ begin_charmode(font)
+ end
+
+ local index = data.index or char
+
+ b = b + 1
+ -- if widefontmode then
+ -- buffer[b] = h_hex[data.index or 0]
+ buffer[b] = h_hex[index]
+ -- elseif char > 255 then
+ -- buffer[b] = f_octal(32)
+ -- elseif char <= 32 or char == 92 or char == 40 or char == 41 or char > 127 then -- \ ( )
+ -- buffer[b] = f_octal(char)
+ -- else
+ -- buffer[b] = f_char(char)
+ -- end
+
+ cw = cw + width
+
+ -- pdfcharacters[fontcharacters[char].index or char] = true
+ pdfcharacters[index] = true
+
+ end
+
+end
+
+-- literals
+
+local flushpdfliteral do
+
+ local literalvalues = nodes.literalvalues
+
+ local originliteral_code = literalvalues.origin
+ local pageliteral_code = literalvalues.page
+ local alwaysliteral_code = literalvalues.always
+ local rawliteral_code = literalvalues.raw
+ local textliteral_code = literalvalues.text
+ local fontliteral_code = literalvalues.font
+
+ local nodeproperties = nodes.properties.data
+
+ flushpdfliteral = function(current,pos_h,pos_v,mode,str)
+ if mode then
+ if not str then
+ mode, str = originliteral_code, mode
+ elseif mode == "mode" then
+ mode = literalvalues[str]
+ if mode == originliteral_code then
+ pdf_goto_pagemode()
+ pdf_set_pos(pos_h,pos_v)
+ elseif mode == pageliteral_code then
+ pdf_goto_pagemode()
+ elseif mode == textliteral_code then
+ pdf_goto_textmode()
+ elseif mode == fontliteral_code then
+ pdf_goto_fontmode()
+ elseif mode == alwaysliteral_code then
+ pdf_end_string_nl()
+ need_tm = true
+ elseif mode == rawliteral_code then
+ pdf_end_string_nl()
+ end
+ return
+ else
+ mode = literalvalues[mode]
+ end
+ else
+ -- str, mode = getdata(current)
+ local p = nodeproperties[current]
+if p then
+ str = p.data
+ mode = p.mode
+else
+ str, mode = getdata(current)
+end
+ end
+ if str and str ~= "" then
+ if mode == originliteral_code then
+ pdf_goto_pagemode()
+ pdf_set_pos(pos_h,pos_v)
+ elseif mode == pageliteral_code then
+ pdf_goto_pagemode()
+ elseif mode == textliteral_code then
+ pdf_goto_textmode()
+ elseif mode == fontliteral_code then
+ pdf_goto_fontmode()
+ elseif mode == alwaysliteral_code then
+ pdf_end_string_nl()
+ need_tm = true
+ elseif mode == rawliteral_code then
+ pdf_end_string_nl()
+ else
+ print("check literal")
+ pdf_goto_pagemode()
+ pdf_set_pos(pos_h,pos_v)
+ end
+ b = b + 1 ; buffer[b] = str
+ end
+ end
+
+ updaters.register("backend.update.pdf",function()
+ function pdf.print(mode,str)
+ if str then
+ mode = literalvalues[mode]
+ else
+ mode, str = originliteral_code, mode
+ end
+ if str and str ~= "" then
+ if mode == originliteral_code then
+ pdf_goto_pagemode()
+ -- pdf_set_pos(pdf_h,pdf_v)
+ elseif mode == pageliteral_code then
+ pdf_goto_pagemode()
+ elseif mode == textliteral_code then
+ pdf_goto_textmode()
+ elseif mode == fontliteral_code then
+ pdf_goto_fontmode()
+ elseif mode == alwaysliteral_code then
+ pdf_end_string_nl()
+ need_tm = true
+ elseif mode == rawliteral_code then
+ pdf_end_string_nl()
+ else
+ pdf_goto_pagemode()
+ -- pdf_set_pos(pdf_h,pdf_v)
+ end
+ b = b + 1 ; buffer[b] = str
+ end
+ end
+ end)
+
+end
+
+-- grouping & orientation
+
+local flushpdfsave, flushpdfrestore, flushpdfsetmatrix do
+
+ local matrices = { }
+ local positions = { }
+ local nofpositions = 0
+ local nofmatrices = 0
+
+ local f_matrix = formatters["%s 0 0 cm"]
+
+ flushpdfsave = function(current,pos_h,pos_v)
+ nofpositions = nofpositions + 1
+ positions[nofpositions] = { pos_h, pos_v, nofmatrices }
+ pdf_goto_pagemode()
+ pdf_set_pos(pos_h,pos_v)
+ b = b + 1 ; buffer[b] = "q"
+ end
+
+ flushpdfrestore = function(current,pos_h,pos_v)
+ if nofpositions < 1 then
+ return
+ end
+ local t = positions[nofpositions]
+ -- local h = pos_h - t[1]
+ -- local v = pos_v - t[2]
+ if shippingmode == "page" then
+ nofmatrices = t[3]
+ end
+ pdf_goto_pagemode()
+ pdf_set_pos(pos_h,pos_v)
+ b = b + 1 ; buffer[b] = "Q"
+ nofpositions = nofpositions - 1
+ end
+
+ local function pdf_set_matrix(str,pos_h,pos_v)
+ if shippingmode == "page" then
+ local rx, sx, sy, ry = splitstring(str," ")
+ if rx and ry and sx and ry then
+ rx, sx, sy, ry = tonumber(rx), tonumber(ry), tonumber(sx), tonumber(sy)
+ local tx = pos_h * (1 - rx) - pos_v * sy
+ local ty = pos_v * (1 - ry) - pos_h * sx
+ if nofmatrices > 1 then
+ local t = matrices[nofmatrices]
+ local r_x, s_x, s_y, r_y, te, tf = t[1], t[2], t[3], t[4], t[5], t[6]
+ rx, sx = rx * r_x + sx * s_y, rx * s_x + sx * r_y
+ sy, ry = sy * r_x + ry * s_y, sy * s_x + ry * r_y
+ tx, ty = tx * r_x + ty * s_y + t_x, tx * s_x + ty * r_y + t_y
+ end
+ nofmatrices = nofmatrices + 1
+ matrices[nofmatrices] = { rx, sx, sy, ry, tx, ty }
+ end
+ end
+ end
+
+ local nodeproperties = nodes.properties.data
+
+ flushpdfsetmatrix = function(current,pos_h,pos_v)
+ local str
+ if type(current) == "string" then
+ str = current
+ else
+ local p = nodeproperties[current]
+ if p then
+ str = p.matrix
+ else
+ str = getdata(current) -- for the moment
+ end
+ end
+ if str and str ~= "" then
+ pdf_set_matrix(str,pos_h,pos_v)
+ pdf_goto_pagemode()
+ pdf_set_pos(pos_h,pos_v)
+ b = b + 1 ; buffer[b] = f_matrix(str)
+ end
+ end
+
+ do
+
+ local function hasmatrix()
+ return nofmatrices > 0
+ end
+
+ local function getmatrix()
+ if nofmatrices > 0 then
+ return unpack(matrices[nofmatrices])
+ else
+ return 0, 0, 0, 0, 0, 0 -- or 1 0 0 1 0 0
+ end
+ end
+
+ updaters.register("backend.update.pdf",function()
+ pdf.hasmatrix = hasmatrix
+ pdf.getmatrix = getmatrix
+ end)
+
+ end
+
+ pushorientation = function(orientation,pos_h,pos_v,pos_r)
+ pdf_goto_pagemode()
+ pdf_set_pos(pos_h,pos_v)
+ b = b + 1 ; buffer[b] = "q"
+ if orientation == 1 then
+ b = b + 1 ; buffer[b] = "0 -1 1 0 0 0 cm" -- 90
+ elseif orientation == 2 then
+ b = b + 1 ; buffer[b] = "-1 0 0 -1 0 0 cm" -- 180
+ elseif orientation == 3 then
+ b = b + 1 ; buffer[b] = "0 1 -1 0 0 0 cm" -- 270
+ end
+ end
+
+ poporientation = function(orientation,pos_h,pos_v,pos_r)
+ pdf_goto_pagemode()
+ pdf_set_pos(pos_h,pos_v)
+ b = b + 1 ; buffer[b] = "Q"
+ end
+
+-- pushorientation = function(orientation,pos_h,pos_v,pos_r)
+-- flushpdfsave(false,pos_h,pos_v)
+-- if orientation == 1 then
+-- flushpdfsetmatrix("0 -1 1 0",pos_h,pos_v)
+-- elseif orientation == 2 then
+-- flushpdfsetmatrix("-1 0 0 -1",pos_h,pos_v)
+-- elseif orientation == 3 then
+-- flushpdfsetmatrix("0 1 -1 0",pos_h,pos_v)
+-- end
+-- end
+
+-- poporientation = function(orientation,pos_h,pos_v,pos_r)
+-- flushpdfrestore(false,pos_h,pos_v)
+-- end
+
+end
+
+-- rules
+
+local flushedxforms = { } -- actually box resources but can also be direct
+
+local flushrule, flushsimplerule do
+
+ local rulecodes = nodes.rulecodes
+ local newrule = nodes.pool.rule
+
+ local setprop = nuts.setprop
+ local getprop = nuts.getprop
+
+ local normalrule_code = rulecodes.normal
+ local boxrule_code = rulecodes.box
+ local imagerule_code = rulecodes.image
+ local emptyrule_code = rulecodes.empty
+ local userrule_code = rulecodes.user
+ local overrule_code = rulecodes.over
+ local underrule_code = rulecodes.under
+ local fractionrule_code = rulecodes.fraction
+ local radicalrule_code = rulecodes.radical
+ local outlinerule_code = rulecodes.outline
+
+ local rule_callback = callbacks.functions.process_rule
+
+ local f_fm = formatters["/Fm%d Do"]
+ local f_im = formatters["/Im%d Do"]
+
+ local s_b = "q"
+ local s_e = "Q"
+
+ local f_v = formatters["[] 0 d 0 J %.6F w 0 0 m %.6F 0 l S"]
+ local f_h = formatters["[] 0 d 0 J %.6F w 0 0 m 0 %.6F l S"]
+
+ local f_f = formatters["0 0 %.6F %.6F re f"]
+ local f_o = formatters["[] 0 d 0 J 0 0 %.6F %.6F re S"]
+ local f_w = formatters["[] 0 d 0 J %.6F w 0 0 %.6F %.6F re S"]
+
+ directives.register("pdf.stripzeros",function()
+ f_v = formatters["[] 0 d 0 J %.6N w 0 0 m %.6N 0 l S"]
+ f_h = formatters["[] 0 d 0 J %.6N w 0 0 m 0 %.6N l S"]
+ f_f = formatters["0 0 %.6N %.6N re f"]
+ f_o = formatters["[] 0 d 0 J 0 0 %.6N %.6N re S"]
+ f_w = formatters["[] 0 d 0 J %.6N w 0 0 %.6N %.6N re S"]
+ end)
+
+ -- Historically the index is an object which is kind of bad.
+
+ local boxresources, n = { }, 0
+
+ getxformname = function(index)
+ local l = boxresources[index]
+ if l then
+ return l.name
+ else
+ print("no box resource",index)
+ end
+ end
+
+ updaters.register("backend.update.pdf",function()
+ pdf.getxformname = getxformname
+ end)
+
+ local function saveboxresource(box,attributes,resources,immediate,kind,margin)
+ n = n + 1
+ local immediate = true
+ local margin = margin or 0 -- or dimension
+ local objnum = pdfreserveobject()
+ local list = tonut(type(box) == "number" and tex.takebox(box) or box)
+ --
+ local width, height, depth = getwhd(list)
+ --
+ local l = {
+ width = width,
+ height = height,
+ depth = depth,
+ margin = margin,
+ attributes = attributes,
+ resources = resources,
+ list = nil,
+ type = kind,
+ name = n,
+ index = objnum,
+ objnum = objnum,
+ }
+ boxresources[objnum] = l
+ if immediate then
+ lpdf.convert(list,"xform",objnum,l)
+ flushedxforms[objnum] = { true , objnum }
+ flushlist(list)
+ else
+ l.list = list
+ end
+ return objnum
+ end
+
+ local function useboxresource(index,wd,ht,dp)
+ local l = boxresources[index]
+ if l then
+ if wd or ht or dp then
+ wd, ht, dp = wd or 0, ht or 0, dp or 0
+ else
+ wd, ht, dp = l.width, l.height, l.depth
+ end
+ local rule = newrule(wd,ht,dp) -- newboxrule
+ rule.subtype = boxrule_code
+ setprop(tonut(rule),"index",index)
+ return rule, wd, ht, dp
+ else
+ print("no box resource",index)
+ end
+ end
+
+ local function getboxresourcedimensions(index)
+ local l = boxresources[index]
+ if l then
+ return l.width, l.height, l.depth, l.margin
+ else
+ print("no box resource",index)
+ end
+ end
+
+ local function getboxresourcebox(index)
+ local l = boxresources[index]
+ if l then
+ return l.list
+ end
+ end
+
+ updaters.register("backend.update.tex",function()
+ tex.saveboxresource = saveboxresource
+ tex.useboxresource = useboxresource
+ tex.getboxresourcedimensions = getboxresourcedimensions
+ tex.getboxresourcebox = getboxresourcebox
+ end)
+
+ -- a bit of a mess: index is now objnum but that has to change to a proper index
+ -- ... an engine inheritance
+
+ local function flushpdfxform(current,pos_h,pos_v,pos_r,size_h,size_v)
+ -- object properties
+ local objnum = getprop(current,"index")
+ local name = getxformname(objnum)
+ local info = flushedxforms[objnum]
+ local r = boxresources[objnum]
+ if not info then
+ info = { false , objnum }
+ flushedxforms[objnum] = info
+ end
+ local wd, ht, dp = getboxresourcedimensions(objnum)
+ -- or: wd, ht, dp = r.width, r.height, r.depth
+ -- sanity check
+ local htdp = ht + dp
+ if wd == 0 or size_h == 0 or htdp == 0 or size_v == 0 then
+ return
+ end
+ -- calculate scale
+ local rx, ry = 1, 1
+ if wd ~= size_h or htdp ~= size_v then
+ rx = size_h / wd
+ ry = size_v / htdp
+ end
+ -- flush the reference
+ usedxforms[objnum] = true
+ pdf_goto_pagemode()
+ calc_pdfpos(pos_h,pos_v)
+ tx = cmtx * bpfactor
+ ty = cmty * bpfactor
+ b = b + 1 ; buffer[b] = s_b
+ b = b + 1 ; buffer[b] = f_cm(rx,0,0,ry,tx,ty)
+ b = b + 1 ; buffer[b] = f_fm(name)
+ b = b + 1 ; buffer[b] = s_e
+ end
+
+ -- place image also used in vf but we can use a different one if
+ -- we need it
+
+ local imagetypes = images.types -- pdf png jpg jp2 jbig2 stream memstream
+ local img_none = imagetypes.none
+ local img_pdf = imagetypes.pdf
+ local img_stream = imagetypes.stream
+ local img_memstream = imagetypes.memstream
+
+ local one_bp = 65536 * bpfactor
+
+ local imageresources, n = { }, 0
+
+ getximagename = function(index)
+ local l = imageresources[index]
+ if l then
+ return l.name
+ else
+ print("no image resource",index)
+ end
+ end
+
+ updaters.register("backend.update.pdf",function()
+ pdf.getximagename = getximagename
+ end)
+
+ local function flushpdfximage(current,pos_h,pos_v,pos_r,size_h,size_v)
+
+ local width,
+ height,
+ depth = getwhd(current)
+ local total = height + depth
+ local transform = getprop(current,"transform") or 0 -- we never set it ... so just use rotation then
+ local index = getprop(current,"index") or 0
+ local kind,
+ xorigin,
+ yorigin,
+ xsize,
+ ysize,
+ rotation,
+ objnum,
+ groupref = pdfincludeimage(index) -- needs to be sorted out, bad name (no longer mixed anyway)
+
+ if not kind then
+ print("invalid image",index)
+ return
+ end
+
+ local rx, sx, sy, ry, tx, ty = 1, 0, 0, 1, 0, 0
+
+ if kind == img_pdf or kind == img_stream or kind == img_memstream then
+ rx, ry, tx, ty = 1/xsize, 1/ysize, xorigin/xsize, yorigin/ysize
+ else
+ -- if kind == img_png then
+ -- -- if groupref > 0 and img_page_group_val == 0 then
+ -- -- img_page_group_val = groupref
+ -- -- end
+ -- end
+ rx, ry = bpfactor, bpfactor
+ end
+
+ if band(transform,7) > 3 then
+ -- mirror
+ rx, tx = -rx, -tx
+ end
+ local t = band(transform + rotation,3)
+ if t == 0 then
+ -- nothing
+ elseif t == 1 then
+ -- rotation over 90 degrees (counterclockwise)
+ rx, sx, sy, ry, tx, ty = 0, rx, -ry, 0, -ty, tx
+ elseif t == 2 then
+ -- rotation over 180 degrees (counterclockwise)
+ rx, ry, tx, ty = -rx, -ry, -tx, -ty
+ elseif t == 3 then
+ -- rotation over 270 degrees (counterclockwise)
+ rx, sx, sy, ry, tx, ty = 0, -rx, ry, 0, ty, -tx
+ end
+
+ rx = rx * width
+ sx = sx * total
+ sy = sy * width
+ ry = ry * total
+ tx = pos_h - tx * width
+ ty = pos_v - ty * total
+
+ local t = transform + rotation
+
+ if band(transform,7) > 3 then
+ t = t + 1
+ end
+
+ t = band(t,3)
+
+ if t == 0 then
+ -- no transform
+ elseif t == 1 then
+ -- rotation over 90 degrees (counterclockwise)
+ tx = tx + width
+ elseif t == 2 then
+ -- rotation over 180 degrees (counterclockwise)
+ tx = tx + width
+ ty = ty + total
+ elseif t == 3 then
+ -- rotation over 270 degrees (counterclockwise)
+ ty = ty + total
+ end
+
+ -- a flaw in original, can go:
+ --
+ -- if img_page_group_val == 0 then
+ -- img_page_group_val = group_ref
+ -- end
+
+ usedximages[index] = objnum -- hm
+
+ pdf_goto_pagemode()
+
+ calc_pdfpos(tx,ty)
+
+ tx = cmtx * bpfactor
+ ty = cmty * bpfactor
+
+ b = b + 1 ; buffer[b] = s_b
+ b = b + 1 ; buffer[b] = f_cm(rx,sx,sy,ry,tx,ty)
+ b = b + 1 ; buffer[b] = f_im(index)
+ b = b + 1 ; buffer[b] = s_e
+ end
+
+ flushpdfimage = function(index,width,height,depth,pos_h,pos_v)
+
+ -- used in vf characters
+
+ local total = height + depth
+ local kind,
+ xorigin, yorigin,
+ xsize, ysize,
+ rotation,
+ objnum,
+ groupref = pdfincludeimage(index)
+
+ local rx = width / xsize
+ local sx = 0
+ local sy = 0
+ local ry = total / ysize
+ local tx = pos_h
+ local ty = pos_v - 2 * depth -- to be sorted out
+
+ usedximages[index] = objnum
+
+ pdf_goto_pagemode()
+
+ calc_pdfpos(tx,ty)
+
+ tx = cmtx * bpfactor
+ ty = cmty * bpfactor
+
+ b = b + 1 ; buffer[b] = s_b
+ b = b + 1 ; buffer[b] = f_cm(rx,sx,sy,ry,tx,ty)
+ b = b + 1 ; buffer[b] = f_im(index)
+ b = b + 1 ; buffer[b] = s_e
+ end
+
+ -- For the moment we need this hack because the engine checks the 'image'
+ -- command in virtual fonts (so we use lua instead).
+
+ pdf.flushpdfimage = flushpdfimage
+
+ flushrule = function(current,pos_h,pos_v,pos_r,size_h,size_v)
+
+ local subtype = getsubtype(current)
+ if subtype == emptyrule_code then
+ return
+ elseif subtype == boxrule_code then
+ return flushpdfxform(current,pos_h,pos_v,pos_r,size_h,size_v)
+ elseif subtype == imagerule_code then
+ return flushpdfximage(current,pos_h,pos_v,pos_r,size_h,size_v)
+ end
+ if subtype == userrule_code or subtype >= overrule_code and subtype <= radicalrule_code then
+ pdf_goto_pagemode()
+ b = b + 1 ; buffer[b] = s_b
+ pdf_set_pos_temp(pos_h,pos_v)
+ rule_callback(current,size_h,size_v,pos_r) -- so we pass direction
+ b = b + 1 ; buffer[b] = s_e
+ return
+ end
+
+ pdf_goto_pagemode()
+
+ -- local saved_b = b
+
+ b = b + 1 ; buffer[b] = s_b
+
+ local dim_h = size_h * bpfactor
+ local dim_v = size_v * bpfactor
+ local rule
+
+ if dim_v <= one_bp then
+ pdf_set_pos_temp(pos_h,pos_v + 0.5 * size_v)
+ rule = f_v(dim_v,dim_h)
+ elseif dim_h <= one_bp then
+ pdf_set_pos_temp(pos_h + 0.5 * size_h,pos_v)
+ rule = f_h(dim_h,dim_v)
+ else
+ pdf_set_pos_temp(pos_h,pos_v)
+ if subtype == outlinerule_code then
+ local linewidth = getdata(current)
+ if linewidth > 0 then
+ rule = f_w(linewidth * bpfactor,dim_h,dim_v)
+ else
+ rule = f_o(dim_h,dim_v)
+ end
+ else
+ rule = f_f(dim_h,dim_v)
+ end
+ end
+
+ b = b + 1 ; buffer[b] = rule
+ b = b + 1 ; buffer[b] = s_e
+
+ -- buffer[saved_b] = concat(buffer," ",saved_b,b)
+ -- b = saved_b
+
+ end
+
+ flushsimplerule = function(pos_h,pos_v,pos_r,size_h,size_v)
+ pdf_goto_pagemode()
+
+ b = b + 1 ; buffer[b] = s_b
+
+ local dim_h = size_h * bpfactor
+ local dim_v = size_v * bpfactor
+ local rule
+
+ if dim_v <= one_bp then
+ pdf_set_pos_temp(pos_h,pos_v + 0.5 * size_v)
+ rule = f_v(dim_v,dim_h)
+ elseif dim_h <= one_bp then
+ pdf_set_pos_temp(pos_h + 0.5 * size_h,pos_v)
+ rule = f_h(dim_h,dim_v)
+ else
+ pdf_set_pos_temp(pos_h,pos_v)
+ rule = f_f(dim_h,dim_v)
+ end
+
+ b = b + 1 ; buffer[b] = rule
+ b = b + 1 ; buffer[b] = s_e
+ end
+
+end
+
+--- basics
+
+local wrapup, registerpage do
+
+ local pages = { }
+ local maxkids = 10
+ local nofpages = 0
+
+ registerpage = function(object)
+ nofpages = nofpages + 1
+ local objnum = pdfpagereference(nofpages)
+ pages[nofpages] = {
+ objnum = objnum,
+ object = object,
+ }
+ end
+
+ wrapup = function()
+
+ -- local includechar = lpdf.includecharlist
+ --
+ -- for font, list in next, usedcharacters do
+ -- includechar(font,keys(list))
+ -- end
+
+ -- hook (to reshuffle pages)
+ local pagetree = { }
+ local parent = nil
+ local minimum = 0
+ local maximum = 0
+ local current = 0
+ if #pages > 1.5 * maxkids then
+ repeat
+ local plist, pnode
+ if current == 0 then
+ plist, minimum = pages, 1
+ elseif current == 1 then
+ plist, minimum = pagetree, 1
+ else
+ plist, minimum = pagetree, maximum + 1
+ end
+ maximum = #plist
+ if maximum > minimum then
+ local kids
+ for i=minimum,maximum do
+ local p = plist[i]
+ if not pnode or #kids == maxkids then
+ kids = pdfarray()
+ parent = pdfreserveobject()
+ pnode = pdfdictionary {
+ objnum = parent,
+ Type = pdf_pages,
+ Kids = kids,
+ Count = 0,
+ }
+ pagetree[#pagetree+1] = pnode
+ end
+ kids[#kids+1] = pdfreference(p.objnum)
+ pnode.Count = pnode.Count + (p.Count or 1)
+ p.Parent = pdfreference(parent)
+ end
+ end
+ current = current + 1
+ until maximum == minimum
+ -- flush page tree
+ for i=1,#pagetree do
+ local entry = pagetree[i]
+ local objnum = entry.objnum
+ entry.objnum = nil
+ pdfflushobject(objnum,entry)
+ end
+ else
+ -- ugly
+ local kids = pdfarray()
+ local list = pdfdictionary {
+ Type = pdf_pages,
+ Kids = kids,
+ Count = nofpages,
+ }
+ parent = pdfreserveobject()
+ for i=1,nofpages do
+ local page = pages[i]
+ kids[#kids+1] = pdfreference(page.objnum)
+ page.Parent = pdfreference(parent)
+ end
+ pdfflushobject(parent,list)
+ end
+ for i=1,nofpages do
+ local page = pages[i]
+ local object = page.object
+ object.Parent = page.Parent
+ pdfflushobject(page.objnum,object)
+ end
+ lpdf.addtocatalog("Pages",pdfreference(parent))
+
+ end
+
+end
+
+pdf_h, pdf_v = 0, 0
+
+local function initialize(specification)
+ reset_variables(specification)
+ reset_buffer()
+end
+
+local f_font = formatters["F%d"]
+local f_form = formatters["Fm%d"]
+local f_image = formatters["Im%d"]
+
+-- This will all move and be merged and become less messy.
+
+-- todo: more clever resource management: a bit tricky as we can inject
+-- stuff in the page stream
+
+local pushmode, popmode
+
+local function finalize(objnum,specification)
+
+ pushmode()
+
+ pdf_goto_pagemode() -- for now
+
+ local content = concat(buffer,"\n",1,b)
+
+ local fonts = nil
+ local xforms = nil
+
+ if next(usedfonts) then
+ fonts = pdfdictionary { }
+ for k, v in next, usedfonts do
+ fonts[f_font(v)] = pdfreference(pdfgetfontobjnumber(k)) -- we can overload for testing
+ end
+ end
+
+ -- messy: use real indexes for both ... so we need to change some in the
+ -- full luatex part
+
+ if next(usedxforms) or next(usedximages) then
+ xforms = pdfdictionary { }
+ for k in sortedhash(usedxforms) do
+ -- xforms[f_form(k)] = pdfreference(k)
+ xforms[f_form(getxformname(k))] = pdfreference(k)
+ end
+ for k, v in sortedhash(usedximages) do
+ xforms[f_image(k)] = pdfreference(v)
+ end
+ end
+
+ reset_buffer()
+
+ -- finish_pdfpage_callback(shippingmode == "page")
+
+ if shippingmode == "page" then
+
+ local pageproperties = lpdf.getpageproperties()
+
+ local pageresources = pageproperties.pageresources
+ local pageattributes = pageproperties.pageattributes
+ local pagesattributes = pageproperties.pagesattributes
+
+ pageresources.Font = fonts
+ pageresources.XObject = xforms
+ pageresources.ProcSet = lpdf.procset()
+
+ local contentsobj = pdfflushstreamobject(content,false,false)
+
+ pageattributes.Type = pdf_page
+ pageattributes.Contents = pdfreference(contentsobj)
+ pageattributes.Resources = pageresources
+ -- pageattributes.Resources = pdfreference(pdfflushobject(pageresources))
+ pageattributes.MediaBox = pdfarray {
+ boundingbox[1] * bpfactor,
+ boundingbox[2] * bpfactor,
+ boundingbox[3] * bpfactor,
+ boundingbox[4] * bpfactor,
+ }
+ pageattributes.Parent = nil -- precalculate
+ pageattributes.Group = nil -- todo
+
+ -- resources can be indirect
+
+ registerpage(pageattributes)
+
+ lpdf.finalizepage(true)
+
+ else
+
+ local xformtype = specification.type or 0
+ local margin = specification.margin or 0
+ local attributes = specification.attributes or ""
+ local resources = specification.resources or ""
+ local wrapper = nil
+ if xformtype == 0 then
+ wrapper = pdfdictionary {
+ Type = pdf_xobject,
+ Subtype = pdf_form,
+ FormType = 1,
+ BBox = nil,
+ Matrix = nil,
+ Resources = nil,
+ }
+ else
+ wrapper = pdfdictionary {
+ BBox = nil,
+ Matrix = nil,
+ Resources = nil,
+ }
+ end
+ if xformtype == 0 or xformtype == 1 or xformtype == 3 then
+ wrapper.BBox = pdfarray {
+ -margin * bpfactor,
+ -margin * bpfactor,
+ (boundingbox[3] + margin) * bpfactor,
+ (boundingbox[4] + margin) * bpfactor,
+ }
+ end
+ if xformtype == 0 or xformtype == 2 or xformtype == 3 then
+ wrapper.Matrix = pdfarray { 1, 0, 0, 1, 0, 0 }
+ end
+
+ -- todo: additional = resources
+
+ local boxresources = lpdf.collectedresources { serialize = false }
+ boxresources.Font = fonts
+ boxresources.XObject = xforms
+
+ -- todo: maybe share them
+ -- wrapper.Resources = pdfreference(pdfflushobject(boxresources))
+
+ if resources ~= "" then
+ boxresources = boxresources + resources
+ end
+ if attributes ~= "" then
+ wrapper = wrapper + attributes
+ end
+
+ wrapper.Resources = next(boxresources) and boxresources or nil
+ wrapper.ProcSet = lpdf.procset()
+
+ -- pdfflushstreamobject(content,wrapper,false,objectnumber)
+ pdfflushstreamobject(content,wrapper,false,specification.objnum)
+
+ end
+
+ for objnum in sortedhash(usedxforms) do
+ local f = flushedxforms[objnum]
+ if f[1] == false then
+ f[1] = true
+ local objnum = f[2] -- specification.objnum
+ local specification = boxresources[objnum]
+ local list = specification.list
+ lpdf.convert(list,"xform",f[2],specification)
+ end
+ end
+
+ pdf_h, pdf_v = 0, 0
+
+ popmode()
+
+end
+
+updaters.register("backend.update.pdf",function()
+ job.positions.registerhandlers {
+ getpos = drivers.getpos,
+ gethpos = drivers.gethpos,
+ getvpos = drivers.getvpos,
+ }
+end)
+
+updaters.register("backend.update",function()
+ local saveboxresource = tex.boxresources.save
+ --
+ -- also in lpdf-res .. brrr .. needs fixing
+ --
+ backends.codeinjections.registerboxresource = function(n,offset)
+ local r = saveboxresource(n,nil,nil,false,0,offset or 0)
+ return r
+ end
+end)
+
+-- now comes the pdf file handling
+
+local objects = { }
+local streams = { } -- maybe just parallel to objects (no holes)
+local nofobjects = 0
+local offset = 0
+local f = false
+local flush = false
+local threshold = 40 -- also #("/Filter /FlateDecode")
+local objectstream = true
+local compress = true
+local cache = false
+local info = ""
+local catalog = ""
+local level = 0
+local lastdeferred = false
+local enginepdf = pdf
+local majorversion = 1
+local minorversion = 7
+local trailerid = true
+
+local f_object = formatters["%i 0 obj\010%s\010endobj\010"]
+local f_stream_n_u = formatters["%i 0 obj\010<< /Length %i >>\010stream\010%s\010endstream\010endobj\010"]
+local f_stream_n_c = formatters["%i 0 obj\010<< /Filter /FlateDecode /Length %i >>\010stream\010%s\010endstream\010endobj\010"]
+local f_stream_d_u = formatters["%i 0 obj\010<< %s /Length %i >>\010stream\010%s\010endstream\010endobj\010"]
+local f_stream_d_c = formatters["%i 0 obj\010<< %s /Filter /FlateDecode /Length %i >>\010stream\010%s\010endstream\010endobj\010"]
+local f_stream_d_r = formatters["%i 0 obj\010<< %s >>\010stream\010%s\010endstream\010endobj\010"]
+
+local f_object_b = formatters["%i 0 obj\010"]
+local f_stream_b_n_u = formatters["%i 0 obj\010<< /Length %i >>\010stream\010"]
+local f_stream_b_n_c = formatters["%i 0 obj\010<< /Filter /FlateDecode /Length %i >>\010stream\010"]
+local f_stream_b_d_u = formatters["%i 0 obj\010<< %s /Length %i >>\010stream\010"]
+local f_stream_b_d_c = formatters["%i 0 obj\010<< %s /Filter /FlateDecode /Length %i >>\010stream\010"]
+local f_stream_b_d_r = formatters["%i 0 obj\010<< %s >>\010stream\010"]
+
+local s_object_e = "\010endobj\010"
+local s_stream_e = "\010endstream\010endobj\010"
+
+do
+
+ local function setinfo() end -- we get it
+ local function setcatalog() end -- we get it
+
+ local function settrailerid(v)
+ trailerid = v or false
+ end
+
+ local function setmajorversion(v) majorversion = tonumber(v) or majorversion end
+ local function setminorversion(v) minorversion = tonumber(v) or minorversion end
+
+ local function getmajorversion(v) return majorversion end
+ local function getminorversion(v) return minorversion end
+
+ local function setcompresslevel (v) compress = v and v ~= 0 and true or false end
+ local function setobjcompresslevel(v) objectstream = v and v ~= 0 and true or false end
+
+ local function getcompresslevel (v) return compress and 3 or 0 end
+ local function getobjcompresslevel(v) return objectstream and 1 or 0 end
+
+ local function setpageresources () end -- needs to be sorted out
+ local function setpageattributes () end
+ local function setpagesattributes() end
+
+ updaters.register("backend.update.pdf",function()
+ pdf.setinfo = setinfo
+ pdf.setcatalog = setcatalog
+ pdf.settrailerid = settrailerid
+ pdf.setmajorversion = setmajorversion
+ pdf.setminorversion = setminorversion
+ pdf.getmajorversion = getmajorversion
+ pdf.getminorversion = getminorversion
+ pdf.setcompresslevel = setcompresslevel
+ pdf.setobjcompresslevel = setobjcompresslevel
+ pdf.getcompresslevel = getcompresslevel
+ pdf.getobjcompresslevel = getobjcompresslevel
+ pdf.setpageresources = setpageresources
+ pdf.setpageattributes = setpageattributes
+ pdf.setpagesattributes = setpagesattributes
+ end)
+
+end
+
+local function pdfreserveobj()
+ nofobjects = nofobjects + 1
+ objects[nofobjects] = false
+ return nofobjects
+end
+
+local addtocache, flushcache, cache do
+
+ local data, d = { }, 0
+ local list, l = { }, 0
+ local coffset = 0
+ local maxsize = 32 * 1024 -- uncompressed
+ local maxcount = 0xFF
+ local indices = { }
+
+ addtocache = function(n,str)
+ local size = #str
+ if size == 0 then
+ -- todo: message
+ return
+ end
+ if coffset + size > maxsize or d == maxcount then
+ flushcache()
+ end
+ if d == 0 then
+ nofobjects = nofobjects + 1
+ objects[nofobjects] = false
+ streams[nofobjects] = indices
+ cache = nofobjects
+ end
+ objects[n] = - cache
+ indices[n] = d
+ d = d + 1
+ -- can have a comment n 0 obj as in luatex
+ data[d] = str
+ l = l + 1 ; list[l] = n
+ l = l + 1 ; list[l] = coffset
+ coffset = coffset + size + 1
+ end
+
+ local p_ObjStm = pdfconstant("ObjStm")
+
+ flushcache = function() -- references cannot be stored
+ if l > 0 then
+ list = concat(list," ")
+ data[0] = list
+ data = concat(data,"\010",0,d)
+ local strobj = pdfdictionary {
+ Type = p_ObjStm,
+ N = d,
+ First = #list + 1,
+ }
+ objects[cache] = offset
+ local b = nil
+ local e = s_stream_e
+ if compress then
+ local comp = zlibcompress(data,3)
+ if comp and #comp < #data then
+ data = comp
+ b = f_stream_b_d_c(cache,strobj(),#data)
+ else
+ b = f_stream_b_d_u(cache,strobj(),#data)
+ end
+ else
+ b = f_stream_b_d_u(cache,strobj(),#data)
+ end
+ flush(f,b)
+ flush(f,data)
+ flush(f,e)
+ offset = offset + #b + #data + #e
+ data, d = { }, 0
+ list, l = { }, 0
+ coffset = 0
+ indices = { }
+ end
+ end
+
+end
+
+local pages = table.setmetatableindex(function(t,k)
+ local v = pdfreserveobj()
+ t[k] = v
+ return v
+end)
+
+local function getpageref(n)
+ return pages[n]
+end
+
+local function refobj()
+ -- not needed, as we have auto-delay
+end
+
+local function flushnormalobj(data,n)
+ if not n then
+ nofobjects = nofobjects + 1
+ n = nofobjects
+ end
+ data = f_object(n,data)
+ if level == 0 then
+ objects[n] = offset
+ offset = offset + #data
+ flush(f,data)
+ else
+ if not lastdeferred then
+ lastdeferred = n
+ elseif n < lastdeferred then
+ lastdeferred = n
+ end
+ objects[n] = data
+ end
+ return n
+end
+
+local function flushstreamobj(data,n,dict,comp,nolength)
+ if not data then
+ print("no data for",dict)
+ return
+ end
+ if not n then
+ nofobjects = nofobjects + 1
+ n = nofobjects
+ end
+ local size = #data
+ if level == 0 then
+ local b = nil
+ local e = s_stream_e
+ if nolength then
+ b = f_stream_b_d_r(n,dict)
+ elseif comp ~= false and compress and size > threshold then
+ local compdata = zlibcompress(data,3)
+ if compdata then
+ local compsize = #compdata
+ if compsize > size - threshold then
+ b = dict and f_stream_b_d_u(n,dict,size) or f_stream_b_n_u(n,size)
+ else
+ data = compdata
+ b = dict and f_stream_b_d_c(n,dict,compsize) or f_stream_b_n_c(n,compsize)
+ end
+ else
+ b = dict and f_stream_b_d_u(n,dict,size) or f_stream_b_n_u(n,size)
+ end
+ else
+ b = dict and f_stream_b_d_u(n,dict,size) or f_stream_b_n_u(n,size)
+ end
+ flush(f,b)
+ flush(f,data)
+ flush(f,e)
+ objects[n] = offset
+ offset = offset + #b + #data + #e
+ else
+ if nolength then
+ data = f_stream_d_r(n,dict,data)
+ elseif comp ~= false and compress and size > threshold then
+ local compdata = zlibcompress(data,3)
+ if compdata then
+ local compsize = #compdata
+ if compsize > size - threshold then
+ data = dict and f_stream_d_u(n,dict,size,data) or f_stream_n_u(n,size,data)
+ else
+ data = dict and f_stream_d_c(n,dict,compsize,compdata) or f_stream_n_c(n,compsize,compdata)
+ end
+ else
+ data = dict and f_stream_d_u(n,dict,size,data) or f_stream_n_u(n,size,data)
+ end
+ else
+ data = dict and f_stream_d_u(n,dict,size,data) or f_stream_n_u(n,size,data)
+ end
+ if not lastdeferred then
+ lastdeferred = n
+ elseif n < lastdeferred then
+ lastdeferred = n
+ end
+ objects[n] = data
+ end
+ return n
+end
+
+local function flushdeferred()
+ if lastdeferred then
+ for n=lastdeferred,nofobjects do
+ local o = objects[n]
+ if type(o) == "string" then
+ objects[n] = offset
+ offset = offset + #o
+ flush(f,o)
+ end
+ end
+ lastdeferred = false
+ end
+end
+
+-- These are already used above, so we define them now:
+
+pushmode = function()
+ level = level + 1
+end
+
+popmode = function()
+ if level == 1 then
+ flushdeferred()
+ end
+ level = level - 1
+end
+
+-- n = pdf.obj([n,] objtext)
+-- n = pdf.obj([n,] "file", filename)
+-- n = pdf.obj([n,] "stream", streamtext [, attrtext])
+-- n = pdf.obj([n,] "streamfile", filename [, attrtext])
+--
+-- n = pdf.obj {
+-- type = <string>, -- raw|stream
+-- immediate = <boolean>,
+-- objnum = <number>,
+-- attr = <string>,
+-- compresslevel = <number>,
+-- objcompression = <boolean>,
+-- file = <string>,
+-- string = <string>,
+-- nolength = <boolean>,
+-- }
+
+local function obj(a,b,c,d)
+ local kind --, immediate
+ local objnum, data, attr, filename
+ local compresslevel, objcompression, nolength
+ local argtype = type(a)
+ if argtype == "table" then
+ kind = a.type -- raw | stream
+ -- immediate = a.immediate
+ objnum = a.objnum
+ attr = a.attr
+ compresslevel = a.compresslevel
+ objcompression = a.objcompression
+ filename = a.file
+ data = a.string or a.stream or ""
+ nolength = a.nolength
+ if kind == "stream" then
+ if filename then
+ data = io.loaddata(filename) or ""
+ end
+ elseif kind == "raw"then
+ if filename then
+ data = io.loaddata(filename) or ""
+ end
+ elseif kind == "file"then
+ kind = "raw"
+ data = filename and io.loaddata(filename) or ""
+ elseif kind == "streamfile" then
+ kind = "stream"
+ data = filename and io.loaddata(filename) or ""
+ end
+ else
+ if argtype == "number" then
+ objnum = a
+ a, b, c = b, c, d
+ else
+ nofobjects = nofobjects + 1
+ objnum = nofobjects
+ end
+ if b then
+ if a == "stream" then
+ kind = "stream"
+ data = b
+ elseif a == "file" then
+ -- kind = "raw"
+ data = io.loaddata(b)
+ elseif a == "streamfile" then
+ kind = "stream"
+ data = io.loaddata(b)
+ else
+ data = "" -- invalid object
+ end
+ attr = c
+ else
+ -- kind = "raw"
+ data = a
+ end
+ end
+ if not objnum then
+ nofobjects = nofobjects + 1
+ objnum = nofobjects
+ end
+ -- todo: immediate
+ if kind == "stream" then
+ flushstreamobj(data,objnum,attr,compresslevel and compresslevel > 0 or nil,nolength)
+ elseif objectstream and objcompression ~= false then
+ addtocache(objnum,data)
+ else
+ flushnormalobj(data,objnum)
+ end
+ return objnum
+end
+
+updaters.register("backend.update.pdf",function()
+ pdf.reserveobj = pdfreserveobj
+ pdf.getpageref = getpageref
+ pdf.refobj = refobj
+ pdf.flushstreamobj = flushstreamobj
+ pdf.flushnormalobj = flushnormalobj
+ pdf.obj = obj
+ pdf.immediateobj = obj
+end)
+
+local openfile, closefile do
+
+ local f_used = formatters["%010i 00000 n \010"]
+ local f_link = formatters["%010i 00000 f \010"]
+ local f_first = formatters["%010i 65535 f \010"]
+ local f_pdf = formatters["%%PDF-%i.%i\010"]
+ local f_xref = formatters["xref\0100 %i\010"]
+ local f_trailer_id = formatters["trailer\010<< %s /ID [ <%s> <%s> ] >>\010startxref\010%i\010%%%%EOF"]
+ local f_trailer_no = formatters["trailer\010<< %s >>\010startxref\010%i\010%%%%EOF"]
+ local f_startxref = formatters["startxref\010%i\010%%%%EOF"]
+
+ local inmemory = false
+ -- local inmemory = environment.arguments.inmemory
+ local close = nil
+
+ openfile = function(filename)
+ if inmemory then
+ f = { }
+ local n = 0
+ flush = function(f,s)
+ n = n + 1 f[n] = s
+ end
+ close = function(f)
+ f = concat(f)
+ io.savedata(filename,f)
+ f = false
+ end
+ else
+ f = io.open(filename,"wb")
+ if not f then
+ -- message
+ os.exit()
+ end
+ flush = getmetatable(f).write
+ close = getmetatable(f).close
+ end
+ local v = f_pdf(majorversion,minorversion)
+ -- local b = "%\xCC\xD5\xC1\xD4\xC5\xD8\xD0\xC4\xC6\010" -- LUATEXPDF (+128)
+ local b = "%\xC3\xCF\xCE\xD4\xC5\xD8\xD4\xD0\xC4\xC6\010" -- CONTEXTPDF (+128)
+ flush(f,v)
+ flush(f,b)
+ offset = #v + #b
+ end
+
+ closefile = function(abort)
+ if not abort then
+ local xrefoffset = offset
+ local lastfree = 0
+ local noffree = 0
+ local catalog = lpdf.getcatalog()
+ local info = lpdf.getinfo()
+ if trailerid == true then
+ trailerid = md5HEX(osuuid())
+ elseif trailerid and #trailerid > 32 then
+ trailerid = md5HEX(trailerid)
+ else
+ trailerid = false
+ end
+ if objectstream then
+ flushdeferred()
+ flushcache()
+ --
+ xrefoffset = offset
+ --
+ nofobjects = nofobjects + 1
+ objects[nofobjects] = offset -- + 1
+ --
+ -- combine these three in one doesn't really give less code so
+ -- we go for the efficient ones
+ --
+ local nofbytes = 4
+ local c1, c2, c3, c4
+ if offset <= 0xFFFF then
+ nofbytes = 2
+ for i=1,nofobjects do
+ local o = objects[i]
+ if not o then
+ noffree = noffree + 1
+ else
+ local strm = o < 0
+ if strm then
+ o = -o
+ end
+ c1 = extract(o,8,8)
+ c2 = extract(o,0,8)
+ if strm then
+ objects[i] = char(2,c1,c2,streams[o][i])
+ else
+ objects[i] = char(1,c1,c2,0)
+ end
+ end
+ end
+ if noffree > 0 then
+ for i=nofobjects,1,-1 do
+ local o = objects[i]
+ if not o then
+ local f1 = extract(lastfree,8,8)
+ local f2 = extract(lastfree,0,8)
+ objects[i] = char(0,f1,f2,0)
+ lastfree = i
+ end
+ end
+ end
+ elseif offset <= 0xFFFFFF then
+ nofbytes = 3
+ for i=1,nofobjects do
+ local o = objects[i]
+ if not o then
+ noffree = noffree + 1
+ else
+ local strm = o < 0
+ if strm then
+ o = -o
+ end
+ c1 = extract(o,16,8)
+ c2 = extract(o, 8,8)
+ c3 = extract(o, 0,8)
+ if strm then
+ objects[i] = char(2,c1,c2,c3,streams[o][i])
+ else
+ objects[i] = char(1,c1,c2,c3,0)
+ end
+ end
+ end
+ if noffree > 0 then
+ for i=nofobjects,1,-1 do
+ local o = objects[i]
+ if not o then
+ local f1 = extract(lastfree,16,8)
+ local f2 = extract(lastfree, 8,8)
+ local f3 = extract(lastfree, 0,8)
+ objects[i] = char(0,f1,f2,f3,0)
+ lastfree = i
+ end
+ end
+ end
+ else
+ nofbytes = 4
+ for i=1,nofobjects do
+ local o = objects[i]
+ if not o then
+ noffree = noffree + 1
+ else
+ local strm = o < 0
+ if strm then
+ o = -o
+ end
+ c1 = extract(o,24,8)
+ c2 = extract(o,16,8)
+ c3 = extract(o, 8,8)
+ c4 = extract(o, 0,8)
+ if strm then
+ objects[i] = char(2,c1,c2,c3,c4,streams[o][i])
+ else
+ objects[i] = char(1,c1,c2,c3,c4,0)
+ end
+ end
+ end
+ if noffree > 0 then
+ for i=nofobjects,1,-1 do
+ local o = objects[i]
+ if not o then
+ local f1 = extract(lastfree,24,8)
+ local f2 = extract(lastfree,16,8)
+ local f3 = extract(lastfree, 8,8)
+ local f4 = extract(lastfree, 0,8)
+ objects[i] = char(0,f1,f2,f3,f4,0)
+ lastfree = i
+ end
+ end
+ end
+ end
+ objects[0] = rep("\0",1+nofbytes+1)
+ local data = concat(objects,"",0,nofobjects)
+ local xref = pdfdictionary {
+ Type = pdfconstant("XRef"),
+ Size = nofobjects + 1,
+ W = pdfarray { 1, nofbytes, 1 },
+ Root = catalog,
+ Info = info,
+ ID = trailerid and pdfarray { pdfliteral(trailerid,true), pdfliteral(trailerid,true) } or nil,
+ }
+ if compress then
+ local comp = zlibcompress(data,3)
+ if comp then
+ data = comp
+ flush(f,f_stream_b_d_c(nofobjects,xref(),#data))
+ else
+ flush(f,f_stream_b_d_u(nofobjects,xref(),#data))
+ end
+ else
+ flush(f,f_stream_b_d_u(nofobjects,xref(),#data))
+ end
+ flush(f,data)
+ flush(f,s_stream_e)
+ flush(f,f_startxref(xrefoffset))
+ else
+ flushdeferred()
+ xrefoffset = offset
+ flush(f,f_xref(nofobjects+1))
+ local trailer = pdfdictionary {
+ Size = nofobjects+1,
+ Root = catalog,
+ Info = info,
+ }
+ for i=1,nofobjects do
+ local o = objects[i]
+ if o then
+ objects[i] = f_used(o)
+ end
+ end
+ for i=nofobjects,1,-1 do
+ local o = objects[i]
+ if not o then
+ objects[i] = f_link(lastfree)
+ lastfree = i
+ end
+ end
+ objects[0] = f_first(lastfree)
+ flush(f,concat(objects,"",0,nofobjects))
+ trailer.Size = nofobjects + 1
+ if trailerid then
+ flush(f,f_trailer_id(trailer(),trailerid,trailerid,xrefoffset))
+ else
+ flush(f,f_trailer_no(trailer(),xrefoffset))
+ end
+ end
+ end
+ close(f)
+ io.flush()
+ end
+
+end
+
+-- For the moment we overload it here, although back-fil.lua eventually will
+-- be merged with back-pdf as it's pdf specific, or maybe back-imp-pdf or so.
+
+updaters.register("backend.update.pdf",function()
+
+ -- We overload img but at some point it will even go away, so we just
+ -- reimplement what we need in context. This will change completely i.e.
+ -- we will drop the low level interface!
+
+ local imagetypes = images.types -- pdf png jpg jp2 jbig2 stream memstream
+ local img_none = imagetypes.none
+
+ local rulecodes = nodes.rulecodes
+ local imagerule_code = rulecodes.image
+
+ local setprop = nodes.nuts.setprop
+
+ local report_images = logs.reporter("backend","images")
+
+ local lastindex = 0
+ local indices = { }
+
+ local bpfactor = number.dimenfactors.bp
+
+ local function new_img(specification)
+ return specification
+ end
+
+ local function copy_img(original)
+ return setmetatableindex(original)
+ end
+
+ local function scan_img(specification)
+ return specification
+ end
+
+ local function embed_img(specification)
+ lastindex = lastindex + 1
+ index = lastindex
+ specification.index = index
+ local xobject = pdfdictionary { }
+ if not specification.notype then
+ xobject.Type = pdfconstant("XObject")
+ xobject.Subtype = pdfconstant("Form")
+ xobject.FormType = 1
+ end
+ local bbox = specification.bbox
+ if bbox and not specification.nobbox then
+ xobject.BBox = pdfarray {
+ bbox[1] * bpfactor,
+ bbox[2] * bpfactor,
+ bbox[3] * bpfactor,
+ bbox[4] * bpfactor,
+ }
+ end
+ xobject = xobject + specification.attr
+ if bbox and not specification.width then
+ specification.width = bbox[3]
+ end
+ if bbox and not specification.height then
+ specification.height = bbox[4]
+ end
+ local dict = xobject()
+ --
+ nofobjects = nofobjects + 1
+ local objnum = nofobjects
+ local nolength = specification.nolength
+ local stream = specification.stream or specification.string
+ --
+ -- We cannot set type in native img so we need this hack or
+ -- otherwise we need to patch too much. Better that i write
+ -- a wrapper then. Anyway, it has to be done better: a key that
+ -- tells either or not to scale by xsize/ysize when flushing.
+ --
+ if not specification.type then
+ local kind = specification.kind
+ if kind then
+ -- take that one
+ elseif attr and find(attr,"BBox") then
+ kind = img_stream
+ else
+ -- hack: a bitmap
+ kind = img_none
+ end
+ specification.type = kind
+ specification.kind = kind
+ end
+ local compress = compresslevel and compresslevel > 0 or nil
+ flushstreamobj(stream,objnum,dict,compress,nolength)
+ specification.objnum = objnum
+ specification.rotation = specification.rotation or 0
+ specification.orientation = specification.orientation or 0
+ specification.transform = specification.transform or 0
+ specification.stream = nil
+ specification.attr = nil
+ specification.type = specification.kind or specification.type or img_none
+ indices[index] = specification -- better create a real specification
+ return specification
+ end
+
+ local function wrap_img(specification)
+ --
+ local index = specification.index
+ if not index then
+ embed_img(specification)
+ end
+ --
+ local width = specification.width or 0
+ local height = specification.height or 0
+ local depth = specification.depth or 0
+ -- newimagerule
+ local n = nodes.pool.rule(width,height,depth)
+ n.subtype = imagerule_code
+ setprop(tonut(n),"index",specification.index)
+ return n
+ end
+
+ -- plugged into the old stuff
+
+ local img = images.__img__
+ img.new = new_img
+ img.copy = copy_img
+ img.scan = scan_img
+ img.embed = embed_img
+ img.wrap = wrap_img
+
+ function pdf.includeimage(index)
+ local specification = indices[index]
+ if specification then
+ local bbox = specification.bbox
+ local xorigin = bbox[1]
+ local yorigin = bbox[2]
+ local xsize = specification.width -- should equal to: bbox[3] - xorigin
+ local ysize = specification.height -- should equal to: bbox[4] - yorigin
+ local transform = specification.transform or 0
+ local objnum = specification.objnum or pdfreserveobj()
+ local groupref = nil
+ local kind = specification.kind or specification.type or img_none -- determines scaling type
+ return
+ kind,
+ xorigin, yorigin,
+ xsize, ysize,
+ transform,
+ objnum,
+ groupref
+ end
+ end
+
+end)
+
+updaters.register("backend.update.lpdf",function()
+
+ -- for the moment here, todo: an md5 or sha2 hash can save space
+
+ local pdfimage = lpdf.epdf.image
+ local newpdf = pdfimage.new
+ local closepdf = pdfimage.close
+ local copypage = pdfimage.copy
+
+ local embedimage = images.embed
+
+ local nofstreams = 0
+ local topdf = { }
+ local toidx = { }
+
+ local function storedata(pdf)
+ local idx = toidx[pdf]
+ if not idx then
+ nofstreams = nofstreams + 1
+ idx = nofstreams
+ toidx[pdf] = nofstreams
+ topdf[idx] = pdf
+ end
+ return idx
+ end
+
+ -- todo: make a type 3 font instead
+
+ -- move to lpdf namespace
+
+ local function vfimage(id,wd,ht,dp,pos_h,pos_v)
+ local index = topdf[id]
+ if type(index) == "string" then
+ local pdfdoc = newpdf(index,#index)
+ local image = copypage(pdfdoc)
+ local bbox = image.bbox
+ image.width = bbox[3] - bbox[1]
+ image.height = bbox[4] - bbox[2]
+ embedimage(image)
+ index = image.index
+ topdf[id] = index
+ end
+ -- pdf.print or pdf.literal
+ pdf.flushpdfimage(index,wd,ht,dp,pos_h,pos_v)
+ end
+
+ local function pdfvfimage(wd,ht,dp,data,name)
+ return { "lua", function(font,char,pos_h,pos_v)
+ local id = storedata(data)
+ vfimage(id,wd,ht,dp,pos_h,pos_v)
+ end }
+ end
+
+ lpdf.vfimage = pdfvfimage
+
+end)
+
+-- The driver.
+
+do
+
+ local isfile = lfs.isfile
+ local removefile = os.remove
+ local renamefile = os.rename
+-- local addsuffix = file.addsuffix
+
+ local pdfname = nil
+ local tmpname = nil
+
+ local function outputfilename()
+ return pdfname
+ end
+
+ local function prepare()
+ if not environment.initex then
+ -- install new functions in pdf namespace
+ updaters.apply("backend.update.pdf")
+ -- install new functions in lpdf namespace
+ updaters.apply("backend.update.lpdf")
+ -- adapt existing shortcuts to lpdf namespace
+ updaters.apply("backend.update.tex")
+ -- adapt existing shortcuts to tex namespace
+ updaters.apply("backend.update")
+ --
+ updaters.apply("backend.update.img")
+ --
+ directives.enable("graphics.uselua")
+ --
+ -- if rawget(pdf,"setforcefile") then
+ -- pdf.setforcefile(false) -- default anyway
+ -- end
+ --
+ pdfname = file.addsuffix(tex.jobname,"pdf")
+ tmpname = "l_m_t_x_" .. pdfname
+ removefile(tmpname)
+ if isfile(tmpname) then
+ report("file %a can't be opened, aborting",tmpname)
+ os.exit()
+ end
+ openfile(tmpname)
+ --
+ luatex.registerstopactions(1,function()
+ lpdf.finalizedocument()
+ closefile()
+ end)
+ --
+ luatex.registerpageactions(1,function()
+ lpdf.finalizepage(true)
+ end)
+ --
+ fonts.constructors.autocleanup = false
+ --
+ lpdf.registerdocumentfinalizer(wrapup,nil,"wrapping up")
+ end
+ --
+ environment.lmtxmode = CONTEXTLMTXMODE
+ end
+
+ local function wrapup()
+ if pdfname then
+ local ok = true
+ if isfile(pdfname) then
+ removefile(pdfname)
+ end
+ if isfile(pdfname) then
+ ok = false
+ else
+ renamefile(tmpname,pdfname)
+ if isfile(tmpname) then
+ ok = false
+ end
+ end
+ if not ok then
+ print(formatters["\nerror in renaming %a to %a\n"](tmpname,pdfname))
+ end
+ pdfname = nil
+ tmpname = nil
+ end
+ end
+
+ local function cleanup()
+ if tmpname then
+ closefile(true)
+ if isfile(tmpname) then
+ removefile(tmpname)
+ end
+ pdfname = nil
+ tmpname = nil
+ end
+ end
+
+ local function convert(boxnumber)
+ lpdf.convert(tex.box[boxnumber],"page")
+ end
+
+ drivers.install {
+ name = "pdf",
+ actions = {
+ prepare = prepare,
+ wrapup = wrapup,
+ convert = convert,
+ cleanup = cleanup,
+ --
+ initialize = initialize,
+ finalize = finalize,
+ updatefontstate = updatefontstate,
+ outputfilename = outputfilename,
+ },
+ flushers = {
+ character = flushcharacter,
+ rule = flushrule,
+ simplerule = flushsimplerule,
+ pushorientation = pushorientation,
+ poporientation = poporientation,
+ --
+ pdfliteral = flushpdfliteral,
+ pdfsetmatrix = flushpdfsetmatrix,
+ pdfsave = flushpdfsave,
+ pdfrestore = flushpdfrestore,
+ pdfimage = flushpdfimage,
+ },
+ }
+
+end
diff --git a/tex/context/base/mkiv/back-lua.lua b/tex/context/base/mkiv/back-lua.lua
new file mode 100644
index 000000000..257fda0a2
--- /dev/null
+++ b/tex/context/base/mkiv/back-lua.lua
@@ -0,0 +1,52 @@
+if not modules then modules = { } end modules ['back-lua'] = {
+ version = 1.001,
+ comment = "companion to lpdf-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local buffer = { }
+local b = 0
+
+local function reset()
+ buffer = { }
+ b = 0
+end
+
+local function initialize(specification)
+ reset()
+end
+
+local function finalize()
+end
+
+local function fetch()
+ local saved = buffer
+ reset()
+ return saved
+end
+
+local function flushcharacter(current, pos_h, pos_v, pod_r, font, char)
+ b = b + 1 ; buffer[b] = { "glyph", font, char, pos_h, pos_v, pos_r }
+end
+
+local function flushrule(current, pos_h, pos_v, pos_r, size_h, size_v)
+ b = b + 1 ; buffer[b] = { "rule", size_h, size_v, pos_h, pos_v, pos_r }
+end
+
+-- file stuff too
+
+drivers.install {
+ name = "lua",
+ actions = {
+ initialize = initialize,
+ finalize = finalize,
+ fetch = fetch,
+ reset = reset,
+ },
+ flushers = {
+ character = flushcharacter,
+ rule = flushrule,
+ }
+}
diff --git a/tex/context/base/mkiv/back-mps.lua b/tex/context/base/mkiv/back-mps.lua
new file mode 100644
index 000000000..380fb7a35
--- /dev/null
+++ b/tex/context/base/mkiv/back-mps.lua
@@ -0,0 +1,94 @@
+if not modules then modules = { } end modules ['back-mps'] = {
+ version = 1.001,
+ comment = "companion to lpdf-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- The basics are the same as the lua variant.
+
+local formatters = string.formatters
+local bpfactor = number.dimenfactors.bp
+
+local buffer = { }
+local b = 0
+
+local function reset()
+ buffer = { }
+ b = 0
+end
+
+local function initialize(specification)
+ reset()
+end
+
+local function finalize()
+end
+
+local function fetch()
+ local saved = buffer
+ reset()
+ return saved
+end
+
+local function flushcharacter(current, pos_h, pos_v, pod_r, font, char)
+ b = b + 1 ; buffer[b] = { "glyph", font, char, pos_h, pos_v, pos_r }
+end
+
+local function flushrule(current, pos_h, pos_v, pod_r, size_h, size_v)
+ b = b + 1 ; buffer[b] = { "rule", size_h, size_v, pos_h, pos_v, pos_r }
+end
+
+drivers.install {
+ name = "mps",
+ actions = {
+ initialize = initialize,
+ finalize = finalize,
+ fetch = fetch,
+ reset = reset,
+ },
+ flushers = {
+ character = flushcharacter,
+ rule = flushrule,
+ }
+}
+
+if not mp then
+ return
+end
+
+local mpprint = mp.print
+
+local f_glyph = formatters[ [[draw textext.drt("\setfontid%i\relax\char%i\relax") shifted (%N,%N);]] ]
+local f_rule = formatters[ [[fill unitsquare xscaled %N yscaled %N shifted (%N,%N);]] ]
+
+local current = nil
+local size = 0
+
+function mp.place_buffermake(box)
+ drivers.convert("mps",box)
+ current = drivers.action("mps","fetch")
+ size = #current
+end
+
+function mp.place_buffersize()
+ mpprint(size)
+end
+
+function mp.place_bufferslot(i)
+ if i > 0 and i <= size then
+ local b = buffer[i]
+ local t = b[1]
+ if t == "glyph" then
+ mpprint(f_glyph(b[2],b[3],b[4]*bpfactor,b[5]*bpfactor))
+ elseif t == "rule" then
+ mpprint(f_rule(b[2]*bpfactor,b[3]*bpfactor,b[4]*bpfactor,b[5]*bpfactor))
+ end
+ end
+end
+
+function mp.place_bufferwipe()
+ current = nil
+ size = 0
+end
diff --git a/tex/context/base/mkiv/back-out.lua b/tex/context/base/mkiv/back-out.lua
new file mode 100644
index 000000000..a0e05afca
--- /dev/null
+++ b/tex/context/base/mkiv/back-out.lua
@@ -0,0 +1,291 @@
+if not modules then modules = { } end modules ['back-out'] = {
+ version = 1.001,
+ comment = "companion to lpdf-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+if CONTEXTLMTXMODE == 0 then
+
+ return
+
+elseif CONTEXTLMTXMODE == 1 then
+
+ local type = type
+ local getdata = nodes.nuts.getdata
+ local loadstring = loadstring
+
+ function backends.latelua(current,pos_h,pos_v,cur_h,cur_v)
+ data = getdata(current)
+ local kind = type(data)
+ if kind == "function" then
+ data()
+ elseif kind == "table" then
+ data.action(data)
+ else
+ -- if kind ~= "string" then
+ -- data = tokentostring(data)
+ -- end
+ if #data ~= "" then
+ local code = loadstring(data)
+ if code then
+ code()
+ end
+ end
+ end
+ end
+
+ return
+end
+
+local type = type
+local loadstring = loadstring
+
+local context = context
+
+-- tokens.scanners.....
+
+local get = token.get_index
+local scaninteger = token.scan_int
+local scanstring = token.scan_string
+local scankeyword = token.scan_keyword
+local scantokenlist = token.scan_tokenlist
+local scancode = token.scan_code
+
+local tokentostring = token.to_string
+
+local logwriter = logs.writer
+local openfile = io.open
+
+local nuts = nodes.nuts
+local tonode = nuts.tonode
+local copynode = nuts.copy
+local nodepool = nuts.pool
+
+local getdata = nuts.getdata
+
+local whatsit_code = nodes.nodecodes.whatsit
+
+local whatsitcodes = nodes.whatsitcodes
+
+local literalvalues = nodes.literalvalues
+local originliteral_code = literalvalues.origin
+local pageliteral_code = literalvalues.page
+local directliteral_code = literalvalues.direct
+local rawliteral_code = literalvalues.raw
+
+local nodeproperties = nodes.properties.data
+
+local channels = { }
+
+local register = nodepool.register
+local newnut = nuts.new
+
+local opennode = register(newnut(whatsit_code,whatsitcodes.open))
+local writenode = register(newnut(whatsit_code,whatsitcodes.write))
+local closenode = register(newnut(whatsit_code,whatsitcodes.close))
+local lateluanode = register(newnut(whatsit_code,whatsitcodes.latelua))
+local literalnode = register(newnut(whatsit_code,whatsitcodes.literal))
+local savenode = register(newnut(whatsit_code,whatsitcodes.save))
+local restorenode = register(newnut(whatsit_code,whatsitcodes.restore))
+local setmatrixnode = register(newnut(whatsit_code,whatsitcodes.setmatrix))
+
+local tomatrix = drivers.helpers.tomatrix
+
+local open_command, write_command, close_command
+
+backends = backends or { }
+
+local function openout(immediate)
+ local channel = scaninteger()
+ scankeyword("=") -- hack
+ local filename = scanstring()
+ if not immediate then
+ local n = copynode(opennode)
+ nodeproperties[n] = { channel = channel, filename = filename } -- action = "open"
+ return context(tonode(n))
+ elseif not channels[channel] then
+ local handle = openfile(filename,"wb") or false
+ if handle then
+ channels[channel] = handle
+ else
+ -- error
+ end
+ end
+end
+
+function backends.openout(n)
+ local p = nodeproperties[n]
+ if p then
+ local handle = openfile(p.filename,"wb") or false
+ if handle then
+ channels[p.channel] = handle
+ else
+ -- error
+ end
+ end
+end
+
+local function write(immediate)
+ local channel = scaninteger()
+ if not immediate then
+ local t = scantokenlist()
+ local n = copynode(writenode)
+ nodeproperties[n] = { channel = channel, data = t } -- action = "write"
+ return context(tonode(n))
+ else
+ local content = scanstring()
+ local handle = channels[channel]
+ if handle then
+ handle:write(content,"\n")
+ else
+ logwriter(content,"\n")
+ end
+ end
+end
+
+function backends.writeout(n)
+ local p = nodeproperties[n]
+ if p then
+ local handle = channels[p.channel]
+ local content = tokentostring(p.data)
+ if handle then
+ handle:write(content,"\n")
+ else
+ logwriter(content,"\n")
+ end
+ end
+end
+
+local function closeout(immediate)
+ local channel = scaninteger()
+ if not immediate then
+ local n = copynode(closenode)
+ nodeproperties[n] = { channel = channel } -- action = "close"
+ return context(tonode(n))
+ else
+ local handle = channels[channel]
+ if handle then
+ handle:close()
+ channels[channel] = false
+ else
+ -- error
+ end
+ end
+end
+
+function backends.closeout(n)
+ local p = nodeproperties[n]
+ if p then
+ local channel = p.channel
+ local handle = channels[channel]
+ if handle then
+ handle:close()
+ channels[channel] = false
+ else
+ -- error
+ end
+ end
+end
+
+local function immediate()
+ local command = scancode()
+ if command == write_command then
+ write(true)
+ elseif command == open_command then
+ openout(true)
+ elseif command == close_command then
+ closeout(true)
+ end
+end
+
+local noflatelua = 0
+
+local function latelua()
+ local node = copynode(lateluanode)
+ local name = "latelua"
+ if scankeyword("name") then
+ name = scanstring()
+ end
+ local data = scantokenlist()
+ nodeproperties[node] = { name = name, data = data }
+ return context(tonode(node))
+end
+
+function backends.latelua(current,pos_h,pos_v,cur_h,cur_v)
+ local p = nodeproperties[current]
+ if p then
+ data = p.data
+ else
+ data = getdata(current)
+ end
+ noflatelua = noflatelua + 1
+ local kind = type(data)
+ if kind == "table" then
+ data.action(data.specification or data)
+ elseif kind == "function" then
+ data()
+ else
+ if kind ~= "string" then
+ data = tokentostring(data)
+ end
+ if #data ~= "" then
+ local code = loadstring(data)
+ if code then
+ code()
+ end
+ end
+ end
+end
+
+function backends.noflatelua()
+ return noflatelua
+end
+
+function nodepool.originliteral(str) local t = copynode(literalnode) nodeproperties[t] = { data = str, mode = originliteral_code } return t end
+function nodepool.pageliteral (str) local t = copynode(literalnode) nodeproperties[t] = { data = str, mode = pageliteral_code } return t end
+function nodepool.directliteral(str) local t = copynode(literalnode) nodeproperties[t] = { data = str, mode = directliteral_code } return t end
+function nodepool.rawliteral (str) local t = copynode(literalnode) nodeproperties[t] = { data = str, mode = rawliteral_code } return t end
+
+local pdfliterals = {
+ [originliteral_code] = originliteral_code, [literalvalues[originliteral_code]] = originliteral_code,
+ [pageliteral_code] = pageliteral_code, [literalvalues[pageliteral_code]] = pageliteral_code,
+ [directliteral_code] = directliteral_code, [literalvalues[directliteral_code]] = directliteral_code,
+ [rawliteral_code] = rawliteral_code, [literalvalues[rawliteral_code]] = rawliteral_code,
+}
+
+function nodepool.literal(mode,str)
+ local t = copynode(literalnode)
+ if str then
+ nodeproperties[t] = { data = str, mode = pdfliterals[mode] or pageliteral_code }
+ else
+ nodeproperties[t] = { data = mode, mode = pageliteral_code }
+ end
+ return t
+end
+
+function nodepool.save()
+ return copynode(savenode)
+end
+
+function nodepool.restore()
+ return copynode(restorenode)
+end
+
+function nodepool.setmatrix(rx,sx,sy,ry,tx,ty)
+ local t = copynode(setmatrixnode)
+ nodeproperties[t] = { matrix = tomatrix(rx,sx,sy,ry,tx,ty) }
+ return t
+end
+
+interfaces.implement { name = "immediate", actions = immediate, public = true, protected = true }
+interfaces.implement { name = "openout", actions = openout, public = true, protected = true }
+interfaces.implement { name = "write", actions = write, public = true, protected = true }
+interfaces.implement { name = "closeout", actions = closeout, public = true, protected = true }
+interfaces.implement { name = "latelua", actions = latelua, public = true, protected = true }
+interfaces.implement { name = "special", actions = scanstring, public = true, protected = true }
+
+open_command = get(token.create("openout"))
+write_command = get(token.create("write"))
+close_command = get(token.create("closeout"))
diff --git a/tex/context/base/mkiv/back-out.mkiv b/tex/context/base/mkiv/back-out.mkiv
new file mode 100644
index 000000000..26548a0a4
--- /dev/null
+++ b/tex/context/base/mkiv/back-out.mkiv
@@ -0,0 +1,23 @@
+%D \module
+%D [ file=back-out,
+%D version=2019.02.08,
+%D title=\CONTEXT\ Backend Macros,
+%D subtitle=Output,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\registerctxluafile{back-out}{}
+
+\let\normalimmediate\immediate
+\let\normalopenout \openout
+\let\normalwrite \write
+\let\normalcloseout \closeout
+\let\normallatelua \latelua
+\let\normalspecial \special
+
+\endinput
diff --git a/tex/context/base/mkiv/back-pdf.lua b/tex/context/base/mkiv/back-pdf.lua
index cc8d31597..8886967e0 100644
--- a/tex/context/base/mkiv/back-pdf.lua
+++ b/tex/context/base/mkiv/back-pdf.lua
@@ -6,10 +6,21 @@ if not modules then modules = { } end modules ['back-pdf'] = {
license = "see context related readme files"
}
+-- We hide the pdf table from users so that we can guarantee no interference with
+-- the way we manage resources, info, etc. Users should use the \type {lpdf}
+-- interface instead. If needed I will provide replacement functionality.
+
interfaces.implement {
name = "setpdfcompression",
arguments = { "integer", "integer" },
actions = lpdf.setcompression,
}
+if CONTEXTLMTXMODE == 0 then
+ updaters.apply("backend.update.pdf")
+ updaters.apply("backend.update.lpdf")
+ updaters.apply("backend.update.tex")
+ updaters.apply("backend.update")
+end
+
backends.install("pdf")
diff --git a/tex/context/base/mkiv/buff-ini.lua b/tex/context/base/mkiv/buff-ini.lua
index 632565fc7..ecb5d9dd0 100644
--- a/tex/context/base/mkiv/buff-ini.lua
+++ b/tex/context/base/mkiv/buff-ini.lua
@@ -167,7 +167,8 @@ local function collectcontent(name,separator) -- no print
elseif nnames == 1 then
return getcontent(names[1])
else
- local t, n = { }, 0
+ local t = { }
+ local n = 0
for i=1,nnames do
local c = getcontent(names[i])
if c ~= "" then
@@ -350,11 +351,17 @@ buffers.undent = undent
-- commands.doifelse(more)
-- end
+local split = table.setmetatableindex(function(t,k)
+ local v = totable(k)
+ t[k] = v
+ return v
+end)
+
function tokens.pickup(start,stop)
- local stoplist = totable(stop)
+ local stoplist = split[stop] -- totable(stop)
local stoplength = #stoplist
local stoplast = stoplist[stoplength]
- local startlist = totable(start)
+ local startlist = split[start] -- totable(start)
local startlength = #startlist
local startlast = startlist[startlength]
local list = { }
diff --git a/tex/context/base/mkiv/buff-ver.lua b/tex/context/base/mkiv/buff-ver.lua
index bfc9ef89c..969a28055 100644
--- a/tex/context/base/mkiv/buff-ver.lua
+++ b/tex/context/base/mkiv/buff-ver.lua
@@ -142,7 +142,8 @@ local functions = { __index = {
local handlers = { }
function visualizers.newhandler(name,data)
- local tname, tdata = type(name), type(data)
+ local tname = type(name)
+ local tdata = type(data)
if tname == "table" then -- (data)
setmetatable(name,getmetatable(name) or functions)
return name
@@ -615,7 +616,12 @@ end
local onlyspaces = S(" \t\f\n\r")^0 * P(-1)
local function getstrip(lines,first,last)
- local first, last = first or 1, last or #lines
+ if not first then
+ first = 1
+ end
+ if not last then
+ last = #lines
+ end
for i=first,last do
local li = lines[i]
if #li == 0 or lpegmatch(onlyspaces,li) then
@@ -741,9 +747,10 @@ local function filter(lines,settings) -- todo: inline or display in settings
if strip ~= v_no and strip ~= false then
lines = realign(lines,strip)
end
- local line, n = 0, 0
- local first, last, m = getstrip(lines)
+ local line = 0
+ local n = 0
local range = settings.range
+ local first, last, m = getstrip(lines)
if range then
first, last = getrange(lines,first,last,range)
first, last = getstrip(lines,first,last)
@@ -810,7 +817,7 @@ local function typestring(settings)
local compact = settings.compact
local compactor = compact and compactors[compact]
if compactor then
- content = lpegmatch(compactor,content)
+ content = lpegmatch(compactor,content) or content
end
-- content = decodecomment(content)
-- content = dotabs(content,settings)
@@ -846,7 +853,7 @@ implement {
actions = typestring,
arguments = {
{
- { "data" },
+ { "data" },
{ "tab" },
{ "method" },
{ "compact" },
@@ -856,6 +863,50 @@ implement {
}
}
+-- implement {
+-- name = "type_x",
+-- actions = typestring,
+-- arguments = {
+-- {
+-- { "data", "verbatim" },
+-- { "tab" },
+-- { "method" },
+-- { "compact" },
+-- { "nature" },
+-- { "escape" },
+-- }
+-- }
+-- }
+
+-- local function typestring_y(settings)
+-- local content = tex.toks[settings.n]
+-- if content and content ~= "" then
+-- local compact = settings.compact
+-- local compactor = compact and compactors[compact]
+-- if compactor then
+-- content = lpegmatch(compactor,content)
+-- end
+-- -- content = decodecomment(content)
+-- -- content = dotabs(content,settings)
+-- visualize(content,checkedsettings(settings,"inline"))
+-- end
+-- end
+
+-- implement {
+-- name = "type_y",
+-- actions = typestring_y,
+-- arguments = {
+-- {
+-- { "n", "integer" },
+-- { "tab" },
+-- { "method" },
+-- { "compact" },
+-- { "nature" },
+-- { "escape" },
+-- }
+-- }
+-- }
+
implement {
name = "processbuffer",
actions = processbuffer,
diff --git a/tex/context/base/mkiv/char-ini.lua b/tex/context/base/mkiv/char-ini.lua
index 62e509151..fb9d9f126 100644
--- a/tex/context/base/mkiv/char-ini.lua
+++ b/tex/context/base/mkiv/char-ini.lua
@@ -617,7 +617,8 @@ characters.otfscripts = otfscripts
setmetatableindex(otfscripts,function(t,unicode)
for k, v in next, blocks do
- local first, last = v.first, v.last
+ local first = v.first
+ local last = v.last
if unicode >= first and unicode <= last then
local script = v.otf or "dflt"
for u=first,last do
@@ -1057,7 +1058,8 @@ setmetatableindex(specialchars, function(t,u)
local c = data[u]
local s = c and c.specials
if s then
- local tt, ttn = { }, 0
+ local tt = { }
+ local ttn = 0
for i=2,#s do
local si = s[i]
local c = data[si]
diff --git a/tex/context/base/mkiv/char-ini.mkiv b/tex/context/base/mkiv/char-ini.mkiv
index 0519aaf91..5979b8685 100644
--- a/tex/context/base/mkiv/char-ini.mkiv
+++ b/tex/context/base/mkiv/char-ini.mkiv
@@ -57,14 +57,34 @@
\unexpanded\def\checkedtextchar#1% #2%
{\clf_doifelsecharinfont\numexpr#1\relax{\char#1}} % {#2}
+% \unexpanded\def\textormathchar#1%
+% {\relax\ifmmode
+% \char#1\relax
+% \else\iffontchar\font#1\relax
+% \char#1\relax
+% \else
+% \normalstartimath\char#1\normalstopimath
+% \fi\fi}
+
+\newconditional\prefermathovertextchar
+
\unexpanded\def\textormathchar#1%
- {\relax\ifmmode
- \char#1\relax
- \else\iffontchar\font#1\relax
- \char#1\relax
+ {\begingroup
+ \scratchcounter#1\relax
+ \ifmmode
+ \char\scratchcounter
\else
- \normalstartimath\char#1\normalstopimath
- \fi\fi}
+ \ifconditional\prefermathovertextchar
+ % dirty trick .. maybe let this adapt to bf too ?
+ \setfontid\fontid\textfont\c_font_fam_mr
+ \fi
+ \iffontchar\font\scratchcounter
+ \char\scratchcounter
+ \else
+ \normalstartimath\char\scratchcounter\normalstopimath
+ \fi
+ \fi
+ \endgroup}
\unexpanded\def\textormathchars#1%
{{\font_text_or_mathchars#1\relax}}
diff --git a/tex/context/base/mkiv/char-tex.lua b/tex/context/base/mkiv/char-tex.lua
index 66997a647..bbaf11875 100644
--- a/tex/context/base/mkiv/char-tex.lua
+++ b/tex/context/base/mkiv/char-tex.lua
@@ -600,14 +600,17 @@ if not csletters then
end
--
if isletter then
- local lc, uc = chr.lccode, chr.uccode
+ local lc = chr.lccode
+ local uc = chr.uccode
if not lc then
- chr.lccode, lc = u, u
+ chr.lccode = u
+ lc = u
elseif type(lc) == "table" then
lc = u
end
if not uc then
- chr.uccode, uc = u, u
+ chr.uccode = u
+ uc = u
elseif type(uc) == "table" then
uc = u
end
@@ -631,12 +634,14 @@ if not csletters then
--
local lc, uc = chr.lccode, chr.uccode
if not lc then
- chr.lccode, lc = u, u
+ chr.lccode = u
+ lc = u
elseif type(lc) == "table" then
lc = u
end
if not uc then
- chr.uccode, uc = u, u
+ chr.uccode = u
+ uc = u
elseif type(uc) == "table" then
uc = u
end
diff --git a/tex/context/base/mkiv/char-utf.lua b/tex/context/base/mkiv/char-utf.lua
index 4dc7eba7a..110a4a48c 100644
--- a/tex/context/base/mkiv/char-utf.lua
+++ b/tex/context/base/mkiv/char-utf.lua
@@ -107,8 +107,10 @@ else
local function backtrack(v,last,target)
local vs = v.specials
if vs and #vs == 3 and vs[1] == "char" then
- local one, two = vs[2], vs[3]
- local first, second = utfchar(one), utfchar(two) .. last
+ local one = vs[2]
+ local two = vs[3]
+ local first = utfchar(one)
+ local second = utfchar(two) .. last
collapsed[first..second] = target
backtrack(data[one],second,target)
end
@@ -141,8 +143,11 @@ else
local size = #vs
if kind == "char" and size == 3 then -- what if more than 3
--
- local one, two = vs[2], vs[3]
- local first, second, combination = utfchar(one), utfchar(two), utfchar(unicode)
+ local one = vs[2]
+ local two = vs[3]
+ local first = utfchar(one)
+ local second = utfchar(two)
+ local combination = utfchar(unicode)
--
collapsed[first..second] = combination
backtrack(data[one],second,combination)
diff --git a/tex/context/base/mkiv/cldf-bas.lua b/tex/context/base/mkiv/cldf-bas.lua
index 4088348f6..f55132a06 100644
--- a/tex/context/base/mkiv/cldf-bas.lua
+++ b/tex/context/base/mkiv/cldf-bas.lua
@@ -195,10 +195,28 @@ context.registers = {
do
- function context.latelua(f)
- local latelua = new_latelua(f)
- setattrlist(latelua,true)
- ctx_flushnode(latelua,true)
+ if CONTEXTLMTXMODE > 1 then
+
+ function context.latelua(f)
+ -- table check moved elsewhere
+ local latelua = new_latelua(f)
+ setattrlist(latelua,true) -- will become an option
+ ctx_flushnode(latelua,true)
+ end
+
+ else
+
+ function context.latelua(f)
+ if type(f) == "table" then
+ local action = f.action
+ local specification = f.specification or f
+ f = function() action(specification) end
+ end
+ local latelua = new_latelua(f)
+ setattrlist(latelua,true) -- will become an option
+ ctx_flushnode(latelua,true)
+ end
+
end
end
diff --git a/tex/context/base/mkiv/cldf-ini.lua b/tex/context/base/mkiv/cldf-ini.lua
index 489ed1158..463ece151 100644
--- a/tex/context/base/mkiv/cldf-ini.lua
+++ b/tex/context/base/mkiv/cldf-ini.lua
@@ -137,7 +137,7 @@ function context.trialtypesetting()
return texgetcount(trialtypesettingstate) ~= 0
end
-local knownfunctions = lua.get_functions_table()
+local knownfunctions = (lua.getfunctionstable or lua.get_functions_table)(true)
local showstackusage = false
trackers.register("context.stack",function(v) showstackusage = v end)
@@ -793,7 +793,7 @@ local function writer(parent,command,...) -- already optimized before call
tj = storefunction(tj)
if tokenflushmode then
if newtoken then
- flush(currentcatcodes,"[",newtoken(tj,lua_expandable_call_code),"]")
+ flush(currentcatcodes,"[",newtoken(tj,lua_expandable_call_token_code),"]")
else
flush(currentcatcodes,"[",t_cldl_luafunction,tj,"]")
end
@@ -811,7 +811,7 @@ local function writer(parent,command,...) -- already optimized before call
tj = storefunction(tj)
if tokenflushmode then
if newtoken then
- flush(currentcatcodes,"[",newtoken(tj,lua_expandable_call_code),j == tn and "]" or ",")
+ flush(currentcatcodes,"[",newtoken(tj,lua_expandable_call_token_code),j == tn and "]" or ",")
else
flush(currentcatcodes,"[",t_cldl_luafunction,tj,j == tn and "]" or ",")
end
@@ -1218,7 +1218,8 @@ local tracedwriter = function(parent,...) -- also catcodes ?
nofwriters = nofwriters + 1
local savedflush = flush
local savedflushdirect = flushdirect -- unlikely to be used here
- local t, n = { "w : - : " }, 1
+ local t = { "w : - : " }
+ local n = 1
local traced = function(catcodes,...) -- todo: check for catcodes
local s = type(catcodes) == "number" and { ... } or { catcodes, ... }
for i=1,#s do
@@ -1262,9 +1263,10 @@ end
local traced = function(one,two,...)
if two ~= nil then
-- only catcodes if 'one' is number
- local catcodes = type(one) == "number" and one
+ local catcodes = type(one) == "number" and one
local arguments = catcodes and { two, ... } or { one, two, ... }
- local collapsed, c = { formatters["f : %s : "](catcodes or '-') }, 1
+ local collapsed = { formatters["f : %s : "](catcodes or '-') }
+ local c = 1
for i=1,#arguments do
local argument = arguments[i]
local argtype = type(argument)
diff --git a/tex/context/base/mkiv/cldf-int.lua b/tex/context/base/mkiv/cldf-int.lua
index a97eadf35..52cfea8d0 100644
--- a/tex/context/base/mkiv/cldf-int.lua
+++ b/tex/context/base/mkiv/cldf-int.lua
@@ -88,9 +88,10 @@ function interfaces.definecommand(name,specification) -- name is optional
else
-- we could flush immediate but tracing is bad then
stack[name] = { }
- local opt, done = 0, false
+ local opt = 0
+ local done = false
local snippets = { } -- we can reuse it
- local mkivdo = "\\mkivdo" .. name -- maybe clddo
+ local mkivdo = "\\mkivdo" .. name -- maybe clddo
snippets[#snippets+1] = "\\def"
snippets[#snippets+1] = mkivdo
for i=1,na do
diff --git a/tex/context/base/mkiv/colo-ini.lua b/tex/context/base/mkiv/colo-ini.lua
index d24939896..3c8d23abc 100644
--- a/tex/context/base/mkiv/colo-ini.lua
+++ b/tex/context/base/mkiv/colo-ini.lua
@@ -312,7 +312,8 @@ local function definetransparency(name,n,global)
end
local settings = settings_to_hash_strict(n)
if settings then
- local a, t = settings.a, settings.t
+ local a = settings.a
+ local t = settings.t
if a and t then
definetransparent(name, transparencies.register(name,transparent[a] or tonumber(a) or 1,tonumber(t) or 1), global)
else
@@ -443,16 +444,23 @@ local function defineprocesscolor(name,str,global,freeze) -- still inconsistent
else
local settings = settings_to_hash_strict(str)
if settings then
- local r, g, b = settings.r, settings.g, settings.b
+ local r = settings.r
+ local g = settings.g
+ local b = settings.b
if r or g or b then
-- we can consider a combined rgb cmyk s definition
definecolor(name, register_color(name,'rgb', tonumber(r) or 0, tonumber(g) or 0, tonumber(b) or 0), global)
else
- local c, m, y, k = settings.c, settings.m, settings.y, settings.k
+ local c = settings.c
+ local m = settings.m
+ local y = settings.y
+ local k = settings.k
if c or m or y or k then
definecolor(name, register_color(name,'cmyk',tonumber(c) or 0, tonumber(m) or 0, tonumber(y) or 0, tonumber(k) or 0), global)
else
- local h, s, v = settings.h, settings.s, settings.v
+ local h = settings.h
+ local s = settings.s
+ local v = settings.v
if v then
r, g, b = colors.hsvtorgb(tonumber(h) or 0, tonumber(s) or 1, tonumber(v) or 1) -- maybe later native
definecolor(name, register_color(name,'rgb',r,g,b), global)
@@ -471,7 +479,8 @@ local function defineprocesscolor(name,str,global,freeze) -- still inconsistent
end
end
end
- local a, t = settings.a, settings.t
+ local a = settings.a
+ local t = settings.t
if a and t then
definetransparent(name, transparencies.register(name,transparent[a] or tonumber(a) or 1,tonumber(t) or 1), global)
elseif colors.couple then
@@ -523,7 +532,8 @@ local function definespotcolor(name,parent,str,global)
do_registerspotcolor(parent,cp,t.e,1,"",tp) -- p not really needed, only diagnostics
if name and name ~= "" then
definecolor(name,register_color(name,'spot',parent,1,"",tp),true)
- local ta, tt = t.a, t.t
+ local ta = t.a
+ local tt = t.t
if ta and tt then
definetransparent(name, transparencies.register(name,transparent[ta] or tonumber(ta) or 1,tonumber(tt) or 1), global)
elseif colors.couple then
@@ -600,7 +610,10 @@ local function definemixcolor(makecolor,name,fractions,cs,global,freeze)
end
local function definemultitonecolor(name,multispec,colorspec,selfspec)
- local dd, pp, nn, max = { }, { }, { }, 0
+ local dd = { }
+ local pp = { }
+ local nn = { }
+ local max = 0
for k,v in gmatch(multispec,"([^=,]+)=([^%,]*)") do -- use settings_to_array
max = max + 1
dd[max] = k
diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv
index f9d8a6b2c..a94cb5d08 100644
--- a/tex/context/base/mkiv/cont-new.mkiv
+++ b/tex/context/base/mkiv/cont-new.mkiv
@@ -11,7 +11,7 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\newcontextversion{2019.02.14 16:57}
+\newcontextversion{2019.04.04 13:31}
%D This file is loaded at runtime, thereby providing an excellent place for
%D hacks, patches, extensions and new features.
@@ -32,12 +32,6 @@
% \let\assumelongusagecs\relax % todo: fails on legends-001.tex
-% experimental
-
-\ifdefined\enablelmtx\else
- \let\enablelmtx\relax
-\fi
-
% done
\protect \endinput
diff --git a/tex/context/base/mkiv/cont-run.mkiv b/tex/context/base/mkiv/cont-run.mkiv
index 3d6103148..f841ce530 100644
--- a/tex/context/base/mkiv/cont-run.mkiv
+++ b/tex/context/base/mkiv/cont-run.mkiv
@@ -22,10 +22,6 @@
\unprotect
-\ifdefined\enablelmtx\else
- \let\enablelmtx\relax
-\fi
-
\let\synctexsetfilename \clf_synctexsetfilename
\let\synctexresetfilename\clf_synctexresetfilename
\let\synctexblockfilename\clf_synctexblockfilename
diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv
index f8ab3d7a6..98d964b24 100644
--- a/tex/context/base/mkiv/context.mkiv
+++ b/tex/context/base/mkiv/context.mkiv
@@ -42,12 +42,12 @@
%D has to match \type {YYYY.MM.DD HH:MM} format.
\edef\contextformat {\jobname}
-\edef\contextversion{2019.02.14 16:57}
+\edef\contextversion{2019.04.04 13:31}
\edef\contextkind {beta}
%D Kind of special:
-\chardef\contextlmtxmode\directlua{tex.print(CONTEXTLMTXMODE and 1 or 0)}\relax
+\chardef\contextlmtxmode\directlua{tex.print(CONTEXTLMTXMODE or 0)}\relax
%D For those who want to use this:
@@ -66,8 +66,6 @@
\def\loadmkiifile#1{}
\def\loadmkivfile#1{\normalinput#1.mkiv\relax}
\def\loadmkvifile#1{\normalinput#1.mkvi\relax}
-\def\loadlmtxfile#1{\ifcase\contextlmtxmode\else\normalinput#1.mkiv\relax\fi}
-
%D First we load the system modules. These implement a lot of
%D manipulation macros. We start with setting up some basic \TEX\
@@ -137,7 +135,7 @@
\loadmkvifile{file-res}
\loadmkvifile{file-lib}
-\loadlmtxfile{core-lmt}
+\loadmarkfile{core-lmt}
% needs more checking for clashes:
%
@@ -600,7 +598,7 @@
\loadmarkfile{cont-run} % the main runner (used in cont-yes.mkiv)
-\loadlmtxfile{driv-shp}
+\loadmarkfile{driv-shp}
\setupcurrentlanguage[\defaultlanguagetag]
diff --git a/tex/context/base/mkiv/core-dat.lua b/tex/context/base/mkiv/core-dat.lua
index dbb14c36e..b49750159 100644
--- a/tex/context/base/mkiv/core-dat.lua
+++ b/tex/context/base/mkiv/core-dat.lua
@@ -108,6 +108,9 @@ end
datasets.setdata = setdata
function datasets.extend(name,tag)
+ if type(name) == "table" then
+ name, tag = name.name, name.tag
+ end
local set = sets[name]
local order = set.order + 1
local realpage = texgetcount("realpageno")
@@ -148,10 +151,8 @@ local function setdataset(settings)
local name, tag = setdata(settings)
if settings.delay ~= v_yes then
--
- elseif type(tag) == "number" then
- context(new_latelua(formatters["job.datasets.extend(%q,%i)"](name,tag)))
else
- context(new_latelua(formatters["job.datasets.extend(%q,%q)"](name,tag)))
+ context(new_latelua { action = job.datasets.extend, name = name, tag = tag })
end
end
diff --git a/tex/context/base/mkiv/core-lmt.mkiv b/tex/context/base/mkiv/core-lmt.mkiv
index 0398537d4..eda667969 100644
--- a/tex/context/base/mkiv/core-lmt.mkiv
+++ b/tex/context/base/mkiv/core-lmt.mkiv
@@ -11,6 +11,8 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
+\ifcase\contextlmtxmode\expandafter\endinput\fi
+
\writestatus{loading}{ConTeXt System Macros / Primitives}
\ifdefined\textdir \else
diff --git a/tex/context/base/mkiv/core-sys.lua b/tex/context/base/mkiv/core-sys.lua
index 4078ab8a8..7e9648fb8 100644
--- a/tex/context/base/mkiv/core-sys.lua
+++ b/tex/context/base/mkiv/core-sys.lua
@@ -53,6 +53,10 @@ function environment.initializefilenames()
environment.filename = filename
environment.suffix = suffix
+ -- if tex then
+ -- tex.jobname = jobfilename
+ -- end
+
report_files("jobname %a, input %a, result %a",jobfilename,inputfilename,outputfilename)
function environment.initializefilenames() end
diff --git a/tex/context/base/mkiv/data-aux.lua b/tex/context/base/mkiv/data-aux.lua
index 1e020d1e8..c57f16d2c 100644
--- a/tex/context/base/mkiv/data-aux.lua
+++ b/tex/context/base/mkiv/data-aux.lua
@@ -50,7 +50,7 @@ function resolvers.updatescript(oldname,newname) -- oldname -> own.name, not per
local newdata = io.loaddata(newscript)
if newdata then
if trace_locating then
- report_scripts("old script content replaced by new content")
+ report_scripts("old script content replaced by new content: %s",oldscript)
end
io.savedata(oldscript,newdata)
break
diff --git a/tex/context/base/mkiv/data-exp.lua b/tex/context/base/mkiv/data-exp.lua
index 76fd3c7b0..ce7f95222 100644
--- a/tex/context/base/mkiv/data-exp.lua
+++ b/tex/context/base/mkiv/data-exp.lua
@@ -344,9 +344,11 @@ local function scan(files,remap,spec,path,n,m,r,onlyone,tolerant)
local pattern = tolerant and lessweird or weird
local filelist = { }
local noffiles = 0
- for name in directory(full) do
+ for name, mode in directory(full) do
if not lpegmatch(pattern,name) then
- local mode = attributes(full..name,"mode")
+ if not mode then
+ mode = attributes(full..name,"mode")
+ end
if mode == "file" then
n = n + 1
noffiles = noffiles + 1
diff --git a/tex/context/base/mkiv/data-tmp.lua b/tex/context/base/mkiv/data-tmp.lua
index 948827161..d25a6b2f9 100644
--- a/tex/context/base/mkiv/data-tmp.lua
+++ b/tex/context/base/mkiv/data-tmp.lua
@@ -68,6 +68,8 @@ caches.ask = false
caches.relocate = false
caches.defaults = { "TMPDIR", "TEMPDIR", "TMP", "TEMP", "HOME", "HOMEPATH" }
+directives.register("system.caches.fast",function(v) caches.fast = true end)
+
local writable, readables, usedreadables = nil, { }, { }
-- we could use a metatable for writable and readable but not yet
@@ -364,7 +366,9 @@ local saveoptions = { compact = true }
function caches.savedata(filepath,filename,data,raw)
local tmaname, tmcname = caches.setluanames(filepath,filename)
data.cache_uuid = os.uuid()
- if caches.direct then
+ if caches.fast then
+ file.savedata(tmaname,table.fastserialize(data,true))
+ elseif caches.direct then
file.savedata(tmaname,table.serialize(data,true,saveoptions))
else
table.tofile(tmaname,data,true,saveoptions)
diff --git a/tex/context/base/mkiv/data-zip.lua b/tex/context/base/mkiv/data-zip.lua
index 6f20b4a9d..388ae0c10 100644
--- a/tex/context/base/mkiv/data-zip.lua
+++ b/tex/context/base/mkiv/data-zip.lua
@@ -37,6 +37,81 @@ zip.archives = archives
local registeredfiles = zip.registeredfiles or { }
zip.registeredfiles = registeredfiles
+local zipfiles = utilities.zipfiles
+
+local openzip, closezip, validfile, wholefile, filehandle, traversezip
+
+if zipfiles then
+
+ local ipairs = ipairs
+
+ openzip = zipfiles.open
+ closezip = zipfiles.close
+ validfile = zipfiles.found
+ wholefile = zipfiles.unzip
+
+ traversezip = function(zfile)
+ return ipairs(zipfiles.list(zfile))
+ end
+
+ local streams = utilities.streams
+ local openstream = streams.open
+ local readstring = streams.readstring
+ local streamsize = streams.size
+
+ local metatable = {
+ close = streams.close,
+ read = function(stream,n)
+ readstring(stream,n == "*a" and streamsize(stream) or n)
+ end
+ }
+
+ filehandle = function(zfile,queryname)
+ local data = wholefile(zfile,queryname)
+ if data then
+ local stream = openstream(data)
+ if stream then
+ return setmetatableindex(stream,metatable)
+ end
+ end
+ end
+
+else
+
+ openzip = zip.open
+ closezip = zip.close
+
+ validfile = function(zfile,queryname)
+ local dfile = zfile:open(queryname)
+ if dfile then
+ dfile:close()
+ return true
+ end
+ return false
+ end
+
+ traversezip = function(zfile)
+ return z:files()
+ end
+
+ wholefile = function(zfile,queryname)
+ local dfile = zfile:open(queryname)
+ if dfile then
+ local s = dfile:read("*all")
+ dfile:close()
+ return s
+ end
+ end
+
+ filehandle = function(zfile,queryname)
+ local dfile = zfile:open(queryname)
+ if dfile then
+ return dfile
+ end
+ end
+
+end
+
local function validzip(str) -- todo: use url splitter
if not find(str,"^zip://") then
return "zip:///" .. str
@@ -52,7 +127,7 @@ function zip.openarchive(name)
local arch = archives[name]
if not arch then
local full = resolvers.findfile(name) or ""
- arch = full ~= "" and zip.open(full) or false
+ arch = full ~= "" and openzip(full) or false
archives[name] = arch
end
return arch
@@ -61,7 +136,7 @@ end
function zip.closearchive(name)
if not name or (name == "" and archives[name]) then
- zip.close(archives[name])
+ closezip(archives[name])
archives[name] = nil
end
end
@@ -106,9 +181,7 @@ function resolvers.finders.zip(specification)
if trace_locating then
report_zip("finder: archive %a found",archive)
end
- local dfile = zfile:open(queryname)
- if dfile then
- dfile:close()
+ if validfile(zfile,queryname) then
if trace_locating then
report_zip("finder: file %a found",queryname)
end
@@ -139,12 +212,12 @@ function resolvers.openers.zip(specification)
if trace_locating then
report_zip("opener; archive %a opened",archive)
end
- local dfile = zfile:open(queryname)
- if dfile then
+ local handle = filehandle(zfile,queryname)
+ if handle then
if trace_locating then
report_zip("opener: file %a found",queryname)
end
- return resolvers.openers.helpers.textopener('zip',original,dfile)
+ return resolvers.openers.helpers.textopener('zip',original,handle)
elseif trace_locating then
report_zip("opener: file %a not found",queryname)
end
@@ -171,15 +244,13 @@ function resolvers.loaders.zip(specification)
if trace_locating then
report_zip("loader: archive %a opened",archive)
end
- local dfile = zfile:open(queryname)
- if dfile then
+ local data = wholefile(zfile,queryname)
+ if data then
logs.show_load(original)
if trace_locating then
report_zip("loader; file %a loaded",original)
end
- local s = dfile:read("*all")
- dfile:close()
- return true, s, #s
+ return true, data, #data
elseif trace_locating then
report_zip("loader: file %a not found",queryname)
end
@@ -231,7 +302,7 @@ function resolvers.registerzipfile(z,tree)
if trace_locating then
report_zip("registering: using filter %a",filter)
end
- for i in z:files() do
+ for i in traversezip(z) do
local filename = i.filename
local path, name = match(filename,filter)
if not path then
diff --git a/tex/context/base/mkiv/driv-ini.lua b/tex/context/base/mkiv/driv-ini.lua
index e16327f27..f3d62c778 100644
--- a/tex/context/base/mkiv/driv-ini.lua
+++ b/tex/context/base/mkiv/driv-ini.lua
@@ -21,11 +21,13 @@ local instances = { }
local helpers = { }
local prepared = { }
local wrappedup = { }
+local cleanedup = { }
local currentdriver = "default"
local prepare = nil
local convert = nil
local wrapup = nil
+local cleanup = nil
local outputfilename = nil
drivers = drivers or {
@@ -42,6 +44,7 @@ local defaulthandlers = {
finalize = dummy,
updatefontstate = dummy,
wrapup = dummy,
+ cleanup = dummy,
convert = dummy,
outputfilename = dummy,
}
@@ -78,13 +81,23 @@ function drivers.outputfilename()
return outputfilename()
end
-
luatex.wrapup(function()
- if not wrappedup[currentdriver] then
+ if wrapup and not wrappedup[currentdriver] then
starttiming(drivers)
wrapup()
stoptiming(drivers)
wrappedup[currentdriver] = true
+ cleanedup[currentdriver] = true
+ end
+end)
+
+luatex.cleanup(function()
+ if cleanup and not cleanedup[currentdriver] then
+ starttiming(drivers)
+ cleanup()
+ stoptiming(drivers)
+ wrappedup[currentdriver] = true
+ cleanedup[currentdriver] = true
end
end)
@@ -93,6 +106,7 @@ function drivers.enable(name)
local actions = instances[currentdriver].actions
prepare = actions.prepare
wrapup = actions.wrapup
+ cleanup = actions.cleanup
convert = actions.convert
outputfilename = actions.outputfilename
--
diff --git a/tex/context/base/mkiv/driv-shp.lua b/tex/context/base/mkiv/driv-shp.lua
new file mode 100644
index 000000000..7938e3e5c
--- /dev/null
+++ b/tex/context/base/mkiv/driv-shp.lua
@@ -0,0 +1,1388 @@
+if not modules then modules = { } end modules ['driv-shp'] = {
+ version = 1.001,
+ comment = "companion to driv-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local type, next = type, next
+local round = math.round
+
+local setmetatableindex = table.setmetatableindex
+local formatters = string.formatters
+local concat = table.concat
+local keys = table.keys
+local sortedhash = table.sortedhash
+local splitstring = string.split
+local idiv = number.idiv
+local extract = bit32.extract
+local nuts = nodes.nuts
+
+local tonut = nodes.tonut
+local tonode = nodes.tonode
+
+local getdirection = nuts.getdirection
+local getlist = nuts.getlist
+local getoffsets = nuts.getoffsets
+local getorientation = nuts.getorientation
+local getfield = nuts.getfield
+local getwhd = nuts.getwhd
+local getkern = nuts.getkern
+local getheight = nuts.getheight
+local getdepth = nuts.getdepth
+local getwidth = nuts.getwidth
+local getnext = nuts.getnext
+local getsubtype = nuts.getsubtype
+local getid = nuts.getid
+local getleader = nuts.getleader
+local getglue = nuts.getglue
+local getshift = nuts.getshift
+local getdata = nuts.getdata
+local getboxglue = nuts.getboxglue
+local getexpansion = nuts.getexpansion
+
+----- getall = node.direct.getall
+
+local setdirection = nuts.setdirection
+local setfield = nuts.setfield
+local setlink = nuts.setlink
+
+local isglyph = nuts.isglyph
+local findtail = nuts.tail
+local nextdir = nuts.traversers.dir
+local nextnode = nuts.traversers.node
+
+local rangedimensions = nuts.rangedimensions
+local effectiveglue = nuts.effective_glue
+
+local nodecodes = nodes.nodecodes
+local whatsitcodes = nodes.whatsitcodes
+local leadercodes = nodes.leadercodes
+local subtypes = nodes.subtypes
+
+local dircodes = nodes.dircodes
+local normaldir_code = dircodes.normal
+
+local dirvalues = nodes.dirvalues
+local lefttoright_code = dirvalues.lefttoright
+local righttoleft_code = dirvalues.righttoleft
+
+local glyph_code = nodecodes.glyph
+local kern_code = nodecodes.kern
+local glue_code = nodecodes.glue
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local dir_code = nodecodes.dir
+local disc_code = nodecodes.disc
+local math_code = nodecodes.math
+local rule_code = nodecodes.rule
+local marginkern_code = nodecodes.marginkern
+local whatsit_code = nodecodes.whatsit
+
+local leader_code = leadercodes.leader
+local cleader_code = leadercodes.cleader
+local xleader_code = leadercodes.xleader
+local gleader_code = leadercodes.gleader
+
+local saveposwhatsit_code = whatsitcodes.savepos
+local userdefinedwhatsit_code = whatsitcodes.userdefined
+local openwhatsit_code = whatsitcodes.open
+local writewhatsit_code = whatsitcodes.write
+local closewhatsit_code = whatsitcodes.close
+local lateluawhatsit_code = whatsitcodes.latelua
+local literalwhatsit_code = whatsitcodes.literal
+local setmatrixwhatsit_code = whatsitcodes.setmatrix
+local savewhatsit_code = whatsitcodes.save
+local restorewhatsit_code = whatsitcodes.restore
+
+local texget = tex.get
+
+local fonthashes = fonts.hashes
+local fontdata = fonthashes.identifiers
+local characters = fonthashes.characters
+local parameters = fonthashes.parameters
+
+local report = logs.reporter("drivers")
+
+local getpagedimensions getpagedimensions = function()
+ getpagedimensions = backends.codeinjections.getpagedimensions
+ return getpagedimensions()
+end
+
+local drivers = drivers
+local instances = drivers.instances
+
+---------------------------------------------------------------------------------------
+
+local synctex = false
+
+local lastfont = nil
+local fontcharacters = nil
+
+local magicconstants = tex.magicconstants
+local trueinch = magicconstants.trueinch
+local maxdimen = magicconstants.maxdimen
+local running = magicconstants.running
+
+local pos_h = 0
+local pos_v = 0
+local pos_r = lefttoright_code
+local shippingmode = "none"
+
+local abs_max_v = 0
+local abs_max_h = 0
+
+local shipbox_h = 0
+local shipbox_v = 0
+local page_size_h = 0
+local page_size_v = 0
+----- page_h_origin = 0 -- trueinch
+----- page_v_origin = 0 -- trueinch
+
+local initialize
+local finalize
+local updatefontstate
+local pushorientation
+local poporientation
+local flushcharacter
+local flushrule
+local flushpdfliteral
+local flushpdfsetmatrix
+local flushpdfsave
+local flushpdfrestore
+local flushspecial
+local flushpdfimage
+
+-- make local
+
+function drivers.getpos () return round(pos_h), round(pos_v) end
+function drivers.gethpos() return round(pos_h) end
+function drivers.getvpos() return round(pos_v) end
+
+-- local function synch_pos_with_cur(ref_h, ref_v, h, v)
+-- if pos_r == righttoleft_code then
+-- pos_h = ref_h - h
+-- else
+-- pos_h = ref_h + h
+-- end
+-- pos_v = ref_v - v
+-- end
+
+-- characters
+
+local flush_character
+
+local stack = setmetatableindex("table")
+local level = 0
+local nesting = 0
+local main = 0
+
+-- todo: cache streams
+
+local function flush_vf_packet(pos_h,pos_v,pos_r,font,char,data,factor,vfcommands)
+
+ if nesting > 100 then
+ return
+ elseif nesting == 0 then
+ main = font
+ end
+
+ nesting = nesting + 1
+
+ local saved_h = pos_h
+ local saved_v = pos_v
+ local saved_r = pos_r
+ pos_r = lefttoright_code
+
+ local data = fontdata[font]
+ local fnt = font
+ local fonts = data.fonts
+ local siz = (data.parameters.factor or 1)/65536
+
+ local function flushchar(font,char,fnt,chr,f,e)
+ if fnt then
+ local nest = char ~= chr or font ~= fnt
+ if fnt == 0 then
+ fnt = main
+ end
+ return flush_character(false,fnt,chr,factor,nest,pos_h,pos_v,pos_r,f,e)
+ else
+ return 0
+ end
+ end
+
+ -- we assume resolved fonts: id mandate but maybe also size
+
+ for i=1,#vfcommands do
+ local packet = vfcommands[i]
+ local command = packet[1]
+ if command == "char" then
+ local chr = packet[2]
+ local f = packet[3]
+ local e = packet[4]
+ pos_h = pos_h + flushchar(font,char,fnt,chr,f,e)
+ elseif command == "slot" then
+ local index = packet[2]
+ local chr = packet[3]
+ local f = packet[4]
+ local e = packet[5]
+ if index == 0 then
+ pos_h = pos_h + flushchar(font,char,font,chr,f,e)
+ else
+ local okay = fonts and fonts[index]
+ if okay then
+ local fnt = okay.id
+ if fnt then
+ pos_h = pos_h + flushchar(font,char,fnt,chr,f,e)
+ end
+ end
+ end
+ elseif command == "right" then
+ local h = packet[2] -- * siz
+ if factor ~= 0 and h ~= 0 then
+ h = h + h * factor / 1000 -- expansion
+ end
+ pos_h = pos_h + h
+ elseif command == "down" then
+ local v = packet[2] -- * siz
+ pos_v = pos_v - v
+ elseif command == "push" then
+ level = level + 1
+ local s = stack[level]
+ s[1] = pos_h
+ s[2] = pos_v
+ elseif command == "pop" then
+ if level > 0 then
+ local s = stack[level]
+ pos_h = s[1]
+ pos_v = s[2]
+ level = level - 1
+ end
+ elseif command == "pdf" then
+ flushpdfliteral(false,pos_h,pos_v,packet[2],packet[3])
+ elseif command == "rule" then
+ local size_v = packet[2]
+ local size_h = packet[3]
+ if factor ~= 0 and size_h > 0 then
+ size_h = size_h + size_h * factor / 1000
+ end
+ if size_h > 0 and size_v > 0 then
+ flushsimplerule(pos_h,pos_v,pos_r,size_h,size_v)
+ pos_h = pos_h + size_h
+ end
+ elseif command == "font" then
+ local index = packet[2]
+ local okay = fonts and fonts[index]
+ if okay then
+ fnt = okay.id or fnt -- or maybe just return
+ end
+ elseif command == "lua" then
+ local code = packet[2]
+ if type(code) ~= "function" then
+ code = loadstring(code)
+ end
+ if type(code) == "function" then
+ code(font,char,pos_h,pos_v)
+ end
+ elseif command == "node" then
+ hlist_out(packet[2])
+ elseif command == "image" then
+ -- doesn't work because intercepted by engine so we use a different
+ -- mechanism (for now)
+ local image = packet[2]
+ -- to do
+ elseif command == "pdfmode" then
+ -- doesn't happen
+ -- elseif command == "special" then
+ -- -- not supported
+ -- elseif command == "nop" then
+ -- -- nothing to do|
+ -- elseif command == "scale" then
+ -- -- not supported
+ end
+ end
+
+ pos_h = saved_h
+ pos_v = saved_v
+ pos_r = saved_r
+
+ -- synch_pos_with_cur(ref_h, ref_v, pos_h,pos_v)
+ nesting = nesting - 1
+end
+
+local onetimemessage -- could be defined later (todo: make plug for this)
+
+flush_character = function(current,font,char,factor,vfcommands,pos_h,pos_v,pos_r,f,e)
+
+ if font ~= lastfont then
+ lastfont = font
+ fontcharacters = characters[font]
+ updatefontstate(font)
+ end
+
+ local data = fontcharacters[char]
+ if not data then
+ if not onetimemessage then
+ onetimemessage = fonts.loggers.onetimemessage
+ end
+ onetimemessage(font,char,"missing")
+ return 0, 0, 0
+ end
+
+ local width, height, depth
+ if current then
+-- width, height, depth = getwhd(current)
+-- factor = getexpansion(current)
+ width, height, depth, factor = getwhd(current,true)
+ if factor ~= 0 then
+ width = (1.0 + factor/1000000.0) * width
+ end
+ else
+ width = data.width or 0
+ height = data.height or 0
+ depth = data.depth or 0
+ if not factor then
+ factor = 0
+ end
+ end
+ if pos_r == righttoleft_code then
+ pos_h = pos_h - width
+ end
+ if vfcommands then
+ vfcommands = data.commands
+ end
+ if vfcommands then
+ flush_vf_packet(pos_h,pos_v,pos_r,font,char,data,factor,vfcommands) -- also f ?
+ else
+ local orientation = data.orientation
+ if orientation and (orientation == 1 or orientation == 3) then
+ local x = data.xoffset
+ local y = data.yoffset
+ if x then
+ pos_h = pos_h + x
+ end
+ if y then
+ pos_v = pos_v + y
+ end
+ pushorientation(orientation,pos_h,pos_v)
+ flushcharacter(current,pos_h,pos_v,pos_r,font,char,data,factor,width,f,e)
+ poporientation(orientation,pos_h,pos_v)
+ else
+ flushcharacter(current,pos_h,pos_v,pos_r,font,char,data,factor,width,f,e)
+ end
+ end
+ return width, height, depth
+end
+
+-- end of characters
+
+local function reset_state()
+ pos_h = 0
+ pos_v = 0
+ pos_r = lefttoright_code
+ shipbox_h = 0
+ shipbox_v = 0
+ shippingmode = "none"
+ page_size_h = 0
+ page_size_v = 0
+ -- page_h_origin = 0 -- trueinch
+ -- page_v_origin = 0 -- trueinch
+end
+
+local function dirstackentry(t,k)
+ local v = {
+ cur_h = 0,
+ cur_v = 0,
+ ref_h = 0,
+ ref_v = 0,
+ }
+ t[k] = v
+ return v
+end
+
+local dirstack = setmetatableindex(dirstackentry)
+
+local function reset_dir_stack()
+ dirstack = setmetatableindex(dirstackentry)
+end
+
+local function flushlatelua(current)
+ return backends.latelua(current)
+end
+
+local function flushwriteout(current)
+ if not doing_leaders then
+ backends.writeout(current)
+ end
+end
+
+local function flushopenout(current)
+ if not doing_leaders then
+ backends.openout(current)
+ end
+end
+
+local function flushcloseout(current)
+ if not doing_leaders then
+ backends.closeout(current)
+ end
+end
+
+local hlist_out, vlist_out do
+
+ -- effective_glue :
+ --
+ -- local cur_g = 0
+ -- local cur_glue = 0.0
+ --
+ -- local width, stretch, shrink, stretch_order, shrink_order = getglue(current)
+ -- if g_sign == 1 then -- stretching
+ -- if stretch_order == g_order then
+ -- -- rule_wd = width - cur_g
+ -- -- cur_glue = cur_glue + stretch
+ -- -- cur_g = g_set * cur_glue
+ -- -- rule_wd = rule_wd + cur_g
+ -- rule_ht = width + g_set * stretch
+ -- else
+ -- rule_wd = width
+ -- end
+ -- else
+ -- if shrink_order == g_order then
+ -- -- rule_wd = width - cur_g
+ -- -- cur_glue = cur_glue - shrink
+ -- -- cur_g = g_set * cur_glue
+ -- -- rule_wd = rule_wd + cur_g
+ -- rule_ht = width - g_set * shrink
+ -- else
+ -- rule_wd = width
+ -- end
+ -- end
+
+ local function applyanchor(orientation,x,y,width,height,depth,woffset,hoffset,doffset,xoffset,yoffset)
+ local ot = extract(orientation, 0,4)
+ local ay = extract(orientation, 4,4)
+ local ax = extract(orientation, 8,4)
+ local of = extract(orientation,12,4)
+ if ot == 4 then
+ ot, ay = 0, 1
+ elseif ot == 5 then
+ ot, ay = 0, 2
+ end
+ if ot == 0 or ot == 2 then
+ if ax == 1 then x = x - width
+ elseif ax == 2 then x = x + width
+ elseif ax == 3 then x = x - width/2
+ elseif ax == 4 then x = x + width/2
+ end
+ if ot == 2 then
+ doffset, hoffset = hoffset, doffset
+ end
+ if ay == 1 then y = y - doffset
+ elseif ay == 2 then y = y + hoffset
+ elseif ay == 3 then y = y + (doffset + hoffset)/2 - doffset
+ end
+ elseif ot == 1 or ot == 3 then
+ if ay == 1 then y = y - height
+ elseif ay == 2 then y = y + height
+ elseif ay == 3 then y = y - height/2
+ end
+ if ot == 1 then
+ doffset, hoffset = hoffset, doffset
+ end
+ if ax == 1 then x = x - width
+ elseif ax == 2 then x = x + width
+ elseif ax == 3 then x = x - width/2
+ elseif ax == 4 then x = x + width/2
+ elseif ax == 5 then x = x - hoffset
+ elseif ax == 6 then x = x + doffset
+ end
+ end
+ return ot, x + xoffset, y - yoffset
+ end
+
+ -- rangedir can stick to widths only
+
+ rangedimensions = node.direct.naturalwidth or rangedimensions
+
+ local function calculate_width_to_enddir(this_box,begindir) -- can be a helper
+ local dir_nest = 1
+ local enddir = begindir
+ for current, subtype in nextdir, getnext(begindir) do
+ if subtype == normaldir_code then -- todo
+ dir_nest = dir_nest + 1
+ else
+ dir_nest = dir_nest - 1
+ end
+ if dir_nest == 0 then -- does the type matter
+ enddir = current
+ local width = rangedimensions(this_box,begindir,enddir)
+ return enddir, width
+ end
+ end
+ if enddir == begindir then
+ local width = rangedimensions(this_box,begindir) -- ,enddir)
+ return enddir, width
+ end
+ return enddir, 0
+ end
+
+ -- check frequencies of nodes
+
+ hlist_out = function(this_box,current)
+ local outer_doing_leaders = false
+
+ local ref_h = pos_h
+ local ref_v = pos_v
+ local ref_r = pos_r
+ pos_r = getdirection(this_box)
+
+ local boxwidth,
+ boxheight,
+ boxdepth = getwhd(this_box)
+ local g_set,
+ g_order,
+ g_sign = getboxglue(this_box)
+
+ local cur_h = 0
+ local cur_v = 0
+
+ if not current then
+ current = getlist(this_box)
+ end
+
+ -- if synctex then
+ -- synctexhlist(this_box)
+ -- end
+
+ while current do
+ local char, id = isglyph(current)
+ if char then
+ local x_offset, y_offset = getoffsets(current)
+ if x_offset ~= 0 or y_offset ~= 0 then
+ -- synch_pos_with_cur(ref_h, ref_v, cur_h + x_offset, cur_v - y_offset)
+ if pos_r == righttoleft_code then
+ pos_h = ref_h - (cur_h + x_offset)
+ else
+ pos_h = ref_h + (cur_h + x_offset)
+ end
+ pos_v = ref_v - (cur_v - y_offset)
+ -- synced
+ end
+ local wd, ht, dp = flush_character(current,id,char,false,true,pos_h,pos_v,pos_r)
+ cur_h = cur_h + wd
+ elseif id == glue_code then
+ local gluewidth
+ if g_sign == 0 then
+ gluewidth = getwidth(current)
+ else
+ gluewidth = effectiveglue(current,this_box)
+ end
+ if gluewidth ~= 0 then
+ local leader = getleader(current)
+ if leader then
+ local width, height, depth = getwhd(leader)
+ if getid(leader) == rule_code then
+ if gluewidth > 0 then
+ if height == running then
+ height = boxheight
+ end
+ if depth == running then
+ depth = boxdepth
+ end
+ local total = height + depth
+ if total > 0 then
+ if pos_r == righttoleft_code then
+ pos_h = pos_h - gluewidth
+ end
+ pos_v = pos_v - depth
+ flushrule(leader,pos_h,pos_v,pos_r,gluewidth,total)
+ end
+ cur_h = cur_h + gluewidth
+ end
+ elseif width > 0 and gluewidth > 0 then
+ local boxdir = getdirection(leader) or lefttoright_code
+ gluewidth = gluewidth + 10
+ local edge = cur_h + gluewidth
+ local lx = 0
+ local subtype = getsubtype(current)
+ if subtype == gleader_code then
+ local save_h = cur_h
+ if pos_r == righttoleft_code then
+ cur_h = ref_h - shipbox_h - cur_h
+ cur_h = width * (cur_h / width)
+ cur_h = ref_h - shipbox_h - cur_h
+ else
+ cur_h = cur_h + ref_h - shipbox_h
+ cur_h = width * (cur_h / width)
+ cur_h = cur_h - ref_h - shipbox_h
+ end
+ if cur_h < save_h then
+ cur_h = cur_h + width
+ end
+ elseif subtype == leader_code then -- aleader ?
+ local save_h = cur_h
+ cur_h = width * (cur_h / width)
+ if cur_h < save_h then
+ cur_h = cur_h + width
+ end
+ else
+ lq = gluewidth / width
+ lr = gluewidth % width
+ if subtype == cleader_code then
+ cur_h = cur_h + lr / 2
+ else
+ lx = lr / (lq + 1)
+ cur_h = cur_h + (lr - (lq - 1) * lx) / 2
+ end
+ end
+ local shift = getshift(leader)
+ while cur_h + width <= edge do
+ local basepoint_h = 0
+ -- local basepoint_v = shift
+ if boxdir ~= pos_r then
+ basepoint_h = boxwidth
+ end
+ -- synch_pos_with_cur(ref_h,ref_v,cur_h + basepoint_h,shift)
+ if pos_r == righttoleft_code then
+ pos_h = ref_h - (cur_h + basepoint_h)
+ else
+ pos_h = ref_h + (cur_h + basepoint_h)
+ end
+ pos_v = ref_v - shift
+ -- synced
+ outer_doing_leaders = doing_leaders
+ doing_leaders = true
+ if getid(leader) == vlist_code then
+ vlist_out(leader)
+ else
+ hlist_out(leader)
+ end
+ doing_leaders = outer_doing_leaders
+ cur_h = cur_h + width + lx
+ end
+ cur_h = edge - 10
+ else
+ cur_h = cur_h + gluewidth
+ -- if synctex then
+ -- synch_pos_with_cur(ref_h, ref_v, cur_h, cur_v)
+ -- synctexhorizontalruleorglue(p, this_box)
+ -- end
+ end
+ else
+ cur_h = cur_h + gluewidth
+ -- if synctex then
+ -- synch_pos_with_cur(ref_h, ref_v, cur_h, cur_v)
+ -- synctexhorizontalruleorglue(p, this_box)
+ -- end
+ end
+ end
+ elseif id == hlist_code or id == vlist_code then
+ -- w h d dir l, s, o = getall(current)
+ local boxdir = getdirection(current) or lefttoright_code
+ local width, height, depth = getwhd(current)
+ local list = getlist(current)
+ if list then
+ local shift, orientation = getshift(current)
+ if not orientation then
+-- local width, height, depth, list, boxdir, shift, orientation = getall(current)
+-- if list then
+-- if not orientation then
+ local basepoint_h = boxdir ~= pos_r and width or 0
+ -- local basepoint_v = shift
+ -- synch_pos_with_cur(ref_h,ref_v,cur_h + basepoint_h,shift)
+ if pos_r == righttoleft_code then
+ pos_h = ref_h - (cur_h + basepoint_h)
+ else
+ pos_h = ref_h + (cur_h + basepoint_h)
+ end
+ pos_v = ref_v - shift
+ -- synced
+ if id == vlist_code then
+ vlist_out(current,list)
+ else
+ hlist_out(current,list)
+ end
+ elseif orientation == 0x1000 then
+ local orientation, xoffset, yoffset = getorientation(current)
+ local basepoint_h = boxdir ~= pos_r and width or 0
+ -- local basepoint_v = shift
+ -- synch_pos_with_cur(ref_h,ref_v,cur_h + basepoint_h + xoffset,shift - yoffset)
+ if pos_r == righttoleft_code then
+ pos_h = ref_h - (cur_h + basepoint_h + xoffset)
+ else
+ pos_h = ref_h + (cur_h + basepoint_h + xoffset)
+ end
+ pos_v = ref_v - (shift - yoffset)
+ -- synced
+ if id == vlist_code then
+ vlist_out(current,list)
+ else
+ hlist_out(current,list)
+ end
+ else
+ local orientation, xoffset, yoffset, woffset, hoffset, doffset = getorientation(current)
+ local orientation, basepoint_h, basepoint_v = applyanchor(orientation,0,shift,width,height,depth,woffset,hoffset,doffset,xoffset,yoffset)
+ if orientation == 1 then
+ basepoint_h = basepoint_h + doffset
+ if boxdir == pos_r then
+ basepoint_v = basepoint_v - height
+ end
+ elseif orientation == 2 then
+ if boxdir == pos_r then
+ basepoint_h = basepoint_h + width
+ end
+ elseif orientation == 3 then
+ basepoint_h = basepoint_h + hoffset
+ if boxdir ~= pos_r then
+ basepoint_v = basepoint_v - height
+ end
+ end
+ -- synch_pos_with_cur(ref_h,ref_v,cur_h+basepoint_h,cur_v + basepoint_v)
+ if pos_r == righttoleft_code then
+ pos_h = ref_h - (cur_h + basepoint_h)
+ else
+ pos_h = ref_h + (cur_h + basepoint_h)
+ end
+ pos_v = ref_v - (cur_v + basepoint_v)
+ -- synced
+ pushorientation(orientation,pos_h,pos_v,pos_r)
+ if id == vlist_code then
+ vlist_out(current,list)
+ else
+ hlist_out(current,list)
+ end
+ poporientation(orientation,pos_h,pos_v,pos_r)
+ end
+ else
+ -- if synctex then
+ -- if id == vlist_code then
+ -- synctexvoidvlist(p,this_box)
+ -- else
+ -- synctexvoidhlist(p,this_box)
+ -- end
+ -- end
+ end
+ cur_h = cur_h + width
+ elseif id == disc_code then
+ local replace = getfield(current,"replace")
+ if replace and getsubtype(current) ~= select_disc then
+ -- we could flatten .. no gain
+ setlink(findtail(replace),getnext(current))
+ setlink(current,replace)
+ setfield(current,"replace")
+ end
+ elseif id == kern_code then
+ -- if synctex then
+ -- synctexkern(p, this_box)
+ -- end
+-- local kern = getkern(current)
+-- local factor = getexpansion(current)
+ local kern, factor = getkern(current,true)
+ if kern ~= 0 then
+ if factor and factor ~= 0 then
+ cur_h = cur_h + (1.0 + factor/1000000.0) * kern
+ else
+ cur_h = cur_h + kern
+ end
+ end
+ elseif id == rule_code then
+ -- w h d x y = getall(current)
+ local width, height, depth = getwhd(current)
+ if width > 0 then
+ if height == running then
+ height = boxheight
+ end
+ if depth == running then
+ depth = boxdepth
+ end
+ local total = height + depth
+ if total > 0 then
+ local xoffset, yoffset, left, right = getoffsets(current)
+ if left ~= 0 then
+ pos_v = pos_v + left
+ total = total - left
+ end
+ if right ~= 0 then
+ depth = depth - right
+ total = total - right
+ end
+ if pos_r == righttoleft_code then
+ pos_h = pos_h - width
+ xoffset = - xoffset
+ end
+ pos_v = pos_v - depth
+ flushrule(current,pos_h + xoffset,pos_v + yoffset,pos_r,width,total)
+ end
+ cur_h = cur_h + width
+ end
+ elseif id == math_code then
+ -- if synctex then
+ -- synctexmath(p, this_box)
+ -- end
+ local kern = getkern(current)
+ if kern ~= 0 then
+ cur_h = cur_h + kern
+ elseif g_sign == 0 then
+ cur_h = cur_h + getwidth(current)
+ else
+ cur_h = cur_h + effectiveglue(current,this_box)
+ end
+ elseif id == dir_code then
+ -- we normally have proper begin-end pairs
+ -- a begin without end is (silently) handled
+ -- an end without a begin will be (silently) skipped
+ -- we only need to move forward so a faster calculation
+ local dir, cancel = getdirection(current)
+ if cancel then
+ local ds = dirstack[current]
+ ref_h = ds.ref_h
+ ref_v = ds.ref_v
+ cur_h = ds.cur_h
+ cur_v = ds.cur_v
+ pos_r = dir
+ else
+ local enddir, width = calculate_width_to_enddir(this_box,current)
+ local ds = dirstack[enddir]
+ ds.cur_h = cur_h + width
+ if dir ~= pos_r then
+ cur_h = ds.cur_h
+ end
+ if enddir ~= current then
+ local ds = dirstack[enddir]
+ ds.cur_v = cur_v
+ ds.ref_h = ref_h
+ ds.ref_v = ref_v
+ setdirection(enddir,pos_r)
+ end
+ -- synch_pos_with_cur(ref_h,ref_v,cur_h,cur_v)
+ if pos_r == righttoleft_code then
+ pos_h = ref_h - cur_h
+ else
+ pos_h = ref_h + cur_h
+ end
+ pos_v = ref_v - cur_v
+ -- synced
+ ref_h = pos_h
+ ref_v = pos_v
+ cur_h = 0
+ cur_v = 0
+ pos_r = dir
+ end
+ elseif id == whatsit_code then
+ local subtype = getsubtype(current)
+ if subtype == literalwhatsit_code then
+ flushpdfliteral(current,pos_h,pos_v)
+ elseif subtype == lateluawhatsit_code then
+ flushlatelua(current,pos_h,pos_v,cur_h,cur_v)
+ elseif subtype == setmatrixwhatsit_code then
+ flushpdfsetmatrix(current,pos_h,pos_v)
+ elseif subtype == savewhatsit_code then
+ flushpdfsave(current,pos_h,pos_v)
+ elseif subtype == restorewhatsit_code then
+ flushpdfrestore(current,pos_h,pos_v)
+ elseif subtype == saveposwhatsit_code then
+ last_position_x = pos_h -- or pdf_h
+ last_position_y = pos_v -- or pdf_v
+ elseif subtype == writewhatsit_code then
+ flushwriteout(current)
+ elseif subtype == closewhatsit_code then
+ flushcloseout(current)
+ elseif subtype == openwhatsit_code then
+ flushopenout(current)
+ end
+ elseif id == marginkern_code then
+ cur_h = cur_h + getkern(current)
+ end
+ current = getnext(current)
+ -- synch_pos_with_cur(ref_h, ref_v, cur_h, cur_v) -- already done in list so skip
+ if pos_r == righttoleft_code then
+ pos_h = ref_h - cur_h
+ else
+ pos_h = ref_h + cur_h
+ end
+ pos_v = ref_v - cur_v
+ -- synced
+ end
+ -- if synctex then
+ -- synctextsilh(this_box)
+ -- end
+ pos_h = ref_h
+ pos_v = ref_v
+ pos_r = ref_r
+ end
+
+ vlist_out = function(this_box,current)
+ local outer_doing_leaders = false
+
+ local ref_h = pos_h
+ local ref_v = pos_v
+ local ref_r = pos_r
+ pos_r = getdirection(this_box)
+
+ local boxwidth,
+ boxheight,
+ boxdepth = getwhd(this_box)
+ local g_set,
+ g_order,
+ g_sign = getboxglue(this_box)
+
+ local cur_h = 0
+ local cur_v = - boxheight
+
+ local top_edge = cur_v
+
+ -- synch_pos_with_cur(ref_h, ref_v, cur_h, cur_v)
+ if pos_r == righttoleft_code then
+ pos_h = ref_h - cur_h
+ else
+ pos_h = ref_h + cur_h
+ end
+ pos_v = ref_v - cur_v
+ -- synced
+
+ if not current then
+ current = getlist(this_box)
+ end
+
+ -- if synctex then
+ -- synctexvlist(this_box)
+ -- end
+
+ -- while current do
+ -- local id = getid(current)
+ for current, id, subtype in nextnode, current do
+ if id == glue_code then
+ local glueheight
+ if g_sign == 0 then
+ glueheight = getwidth(current)
+ else
+ glueheight = effectiveglue(current,this_box)
+ end
+ local leader = getleader(current)
+ if leader then
+ local width, height, depth = getwhd(leader)
+ local total = height + depth
+ if getid(leader) == rule_code then
+ depth = 0 -- hm
+ if total > 0 then
+ if width == running then
+ width = boxwidth
+ end
+ if width > 0 then
+ if pos_r == righttoleft_code then
+ cur_h = cur_h - width
+ end
+ flushrule(leader,pos_h,pos_v - total,pos_r,width,total)
+ end
+ cur_v = cur_v + total
+ end
+ else
+ if total > 0 and glueheight > 0 then
+ glueheight = glueheight + 10
+ local edge = cur_v + glueheight
+ local ly = 0
+ if subtype == gleader_code then
+ save_v = cur_v
+ cur_v = ref_v - shipbox_v - cur_v
+ cur_v = total * (cur_v / total)
+ cur_v = ref_v - shipbox_v - cur_v
+ if cur_v < save_v then
+ cur_v = cur_v + total
+ end
+ elseif subtype == leader_code then -- aleader
+ save_v = cur_v
+ cur_v = top_edge + total * ((cur_v - top_edge) / total)
+ if cur_v < save_v then
+ cur_v = cur_v + total
+ end
+ else
+ lq = glueheight / total
+ lr = glueheight % total
+ if subtype == cleaders_code then
+ cur_v = cur_v + lr / 2
+ else
+ ly = lr / (lq + 1)
+ cur_v = cur_v + (lr - (lq - 1) * ly) / 2
+ end
+ end
+ local shift = getshift(leader)
+ while cur_v + total <= edge do -- todo: <= edge - total
+ -- synch_pos_with_cur(ref_h, ref_v, getshift(leader), cur_v + height)
+ if pos_r == righttoleft_code then
+ pos_h = ref_h - shift
+ else
+ pos_h = ref_h + shift
+ end
+ pos_v = ref_v - (cur_v + height)
+ -- synced
+ outer_doing_leaders = doing_leaders
+ doing_leaders = true
+ if getid(leader) == vlist_code then
+ vlist_out(leader)
+ else
+ hlist_out(leader)
+ end
+ doing_leaders = outer_doing_leaders
+ cur_v = cur_v + total + ly
+ end
+ cur_v = edge - 10
+ else
+ cur_v = cur_v + glueheight
+ end
+ end
+ else
+ cur_v = cur_v + glueheight
+ end
+ elseif id == hlist_code or id == vlist_code then
+ -- w h d dir l, s, o = getall(current)
+ local boxdir = getdirection(current) or lefttoright_code
+ local width, height, depth = getwhd(current)
+ local list = getlist(current)
+ if list then
+ local shift, orientation = getshift(current)
+ if not orientation then
+-- local width, height, depth, list, boxdir, shift, orientation = getall(current)
+-- if list then
+-- if not orientation then
+ -- local basepoint_h = shift
+ -- local basepoint_v = height
+ if boxdir ~= pos_r then
+ shift = shift + width
+ end
+ -- synch_pos_with_cur(ref_h,ref_v,shift,cur_v + height)
+ if pos_r == righttoleft_code then
+ pos_h = ref_h - shift
+ else
+ pos_h = ref_h + shift
+ end
+ pos_v = ref_v - (cur_v + height)
+ -- synced
+ if id == vlist_code then
+ vlist_out(current,list)
+ else
+ hlist_out(current,list)
+ end
+ elseif orientation == 0x1000 then
+ local orientation, xoffset, yoffset = getorientation(current)
+ -- local basepoint_h = shift
+ -- local basepoint_v = height
+ if boxdir ~= pos_r then
+ shift = shift + width
+ end
+ -- synch_pos_with_cur(ref_h,ref_v,shift + xoffset,cur_v + height - yoffset)
+ if pos_r == righttoleft_code then
+ pos_h = ref_h - (shift + xoffset)
+ else
+ pos_h = ref_h + (shift + xoffset)
+ end
+ pos_v = ref_v - (cur_v + height - yoffset)
+ -- synced
+ if id == vlist_code then
+ vlist_out(current,list)
+ else
+ hlist_out(current,list)
+ end
+ else
+ local orientation, xoffset, yoffset, woffset, hoffset, doffset = getorientation(current)
+ local orientation, basepoint_h, basepoint_v = applyanchor(orientation,shift,height,width,height,depth,woffset,hoffset,doffset,xoffset,yoffset)
+ if orientation == 1 then
+ basepoint_h = basepoint_h + width - height
+ basepoint_v = basepoint_v - height
+ elseif orientation == 2 then
+ basepoint_h = basepoint_h + width
+ basepoint_v = basepoint_v + depth - height
+ elseif orientation == 3 then -- weird
+ basepoint_h = basepoint_h + height
+ end
+ -- synch_pos_with_cur(ref_h,ref_v,basepoint_h,cur_v + basepoint_v)
+ if pos_r == righttoleft_code then
+ pos_h = ref_h - basepoint_h
+ else
+ pos_h = ref_h + basepoint_h
+ end
+ pos_v = ref_v - (cur_v + basepoint_v)
+ -- synced
+ pushorientation(orientation,pos_h,pos_v,pos_r)
+ if id == vlist_code then
+ vlist_out(current,list)
+ else
+ hlist_out(current,list)
+ end
+ poporientation(orientation,pos_h,pos_v,pos_r)
+ end
+ else
+ -- if synctex then
+ -- synch_pos_with_cur(ref_h, ref_v, cur_h, cur_v)
+ -- if id == vlist_code then
+ -- synctexvoidvlist(current, this_box)
+ -- else
+ -- synctexvoidhlist(current, this_box)
+ -- end
+ -- end
+ end
+ cur_v = cur_v + height + depth
+ elseif id == kern_code then
+ cur_v = cur_v + getkern(current)
+ elseif id == rule_code then
+ -- w h d x y = getall(current)
+ local width, height, depth = getwhd(current)
+ local total = height + depth
+ if total > 0 then
+ if width == running then
+ width = boxwidth
+ end
+ if width > 0 then
+ local xoffset, yoffset, left, right = getoffsets(current)
+ if left ~= 0 then
+ width = width - left
+ cur_h = cur_h + left
+ end
+ if right ~= 0 then
+ width = width - right
+ end
+ if pos_r == righttoleft_code then
+ cur_h = cur_h - width
+ xoffset = - xoffset
+ end
+ flushrule(current,pos_h + xoffset,pos_v - total - yoffset,pos_r,width,total)
+ end
+ cur_v = cur_v + total
+ end
+ elseif id == whatsit_code then
+ if subtype == literalwhatsit_code then
+ flushpdfliteral(current,pos_h,pos_v)
+ elseif subtype == lateluawhatsit_code then
+ flushlatelua(current,pos_h,pos_v,cur_h,cur_v)
+ elseif subtype == setmatrixwhatsit_code then
+ flushpdfsetmatrix(current,pos_h,pos_v)
+ elseif subtype == savewhatsit_code then
+ flushpdfsave(current,pos_h,pos_v)
+ elseif subtype == restorewhatsit_code then
+ flushpdfrestore(current,pos_h,pos_v)
+ elseif subtype == saveposwhatsit_code then
+ last_position_x = pos_h -- or pdf_h
+ last_position_y = pos_v -- or pdf_v
+ elseif subtype == writewhatsit_code then
+ flushwriteout(current)
+ elseif subtype == closewhatsit_code then
+ flushcloseout(current)
+ elseif subtype == openwhatsit_code then
+ flushopenout(current)
+ end
+ end
+ -- synch_pos_with_cur(ref_h, ref_v, cur_h, cur_v)
+ if pos_r == righttoleft_code then
+ pos_h = ref_h - cur_h
+ else
+ pos_h = ref_h + cur_h
+ end
+ pos_v = ref_v - cur_v
+ -- synced
+ end
+ -- if synctex then
+ -- synctextsilh(this_box)
+ -- end
+ pos_h = ref_h
+ pos_v = ref_v
+ pos_r = ref_r
+ end
+
+end
+
+function lpdf.convert(box,smode,objnum,specification) -- temp name
+
+ if box then
+ box = tonut(box)
+ else
+ report("error in converter, no box")
+ return
+ end
+
+ local driver = instances.pdf
+ if driver then
+ -- tracing
+ else
+ return
+ end
+
+ local actions = driver.actions
+ local flushers = driver.flushers
+
+ initialize = actions.initialize
+ finalize = actions.finalize
+ updatefontstate = actions.updatefontstate
+
+ pushorientation = flushers.pushorientation
+ poporientation = flushers.poporientation
+
+ flushcharacter = flushers.character
+ flushrule = flushers.rule
+ flushsimplerule = flushers.simplerule
+ flushspecial = flushers.special
+ flushpdfliteral = flushers.pdfliteral
+ flushpdfsetmatrix = flushers.pdfsetmatrix
+ flushpdfsave = flushers.pdfsave
+ flushpdfrestore = flushers.pdfrestore
+ flushpdfimage = flushers.pdfimage
+
+ reset_dir_stack()
+ reset_state()
+
+ shippingmode = smode
+
+ -- synctex = texget("synctex")
+
+ -- if synctex then
+ -- synctexsheet(1000)
+ -- end
+
+ local width, height, depth = getwhd(box)
+
+ local total = height + depth
+
+ ----- v_offset_par = 0
+ ----- h_offset_par = 0
+
+ local max_v = total -- + v_offset_par
+ local max_h = width -- + h_offset_par
+
+ if height > maxdimen or depth > maxdimen or width > maxdimen then
+ goto DONE
+ end
+
+ if max_v > maxdimen then
+ goto DONE
+ elseif max_v > abs_max_v then
+ abs_max_v = max_v
+ end
+
+ if max_h > maxdimen then
+ goto DONE
+ elseif max_h > abs_max_h then
+ abs_max_h = max_h
+ end
+
+ if shippingmode == "page" then
+
+ -- We have zero offsets in ConTeXt.
+
+ local pagewidth, pageheight = getpagedimensions()
+ -- local h_offset_par, v_offset_par = texget("hoffset"), texget("voffset")
+
+ -- page_h_origin = trueinch
+ -- page_v_origin = trueinch
+
+ pos_r = lefttoright_code
+
+ if pagewidth > 0 then
+ page_size_h = pagewidth
+ else
+ page_size_h = width
+ end
+
+ if page_size_h == 0 then
+ page_size_h = width
+ end
+
+ if pageheight > 0 then
+ page_size_v = pageheight
+ else
+ page_size_v = total
+ end
+
+ if page_size_v == 0 then
+ page_size_v = total
+ end
+
+ local refpoint_h = 0 -- + page_h_origin + h_offset_par
+ local refpoint_v = page_size_v -- - page_v_origin - v_offset_par
+
+ -- synch_pos_with_cur(refpoint_h,refpoint_v,0,height)
+ if pos_r == righttoleft_code then
+ pos_h = refpoint_h
+ else
+ pos_h = refpoint_h
+ end
+ pos_v = refpoint_v - height
+ -- synced
+
+ else
+
+ -- page_h_origin = 0
+ -- page_v_origin = 0
+ page_size_h = width
+ page_size_v = total
+ pos_r = getdirection(box)
+ pos_v = depth
+ pos_h = pos_r == righttoleft_code and width or 0
+
+ end
+
+ shipbox_ref_h = pos_h
+ shipbox_ref_v = pos_v
+
+ initialize {
+ shippingmode = smode, -- target
+ boundingbox = { 0, 0, page_size_h, page_size_v },
+ objectnumber = objnum,
+ }
+
+ if getid(box) == vlist_code then
+ vlist_out(box)
+ else
+ hlist_out(box)
+ end
+
+ ::DONE::
+
+ -- if synctex then
+ -- synctexteehs()
+ -- end
+
+ finalize(objnum,specification)
+ shippingmode = "none"
+end
+
+-- This will move to back-out.lua eventually.
+
+do
+
+ ----- sortedhash = table.sortedhash
+
+ ----- tonut = nodes.tonut
+ local properties = nodes.properties.data
+ local flush = texio.write_nl
+
+ local periods = utilities.strings.newrepeater(".")
+
+ local function showdetails(n,l)
+ local p = properties[tonut(n)]
+ if p then
+ local done = false
+ for k, v in sortedhash(p) do
+ if done then
+ flush("\n")
+ else
+ done = true
+ end
+ flush(periods[l+1] .. " " .. k .. " = " .. tostring(v))
+ end
+ end
+ end
+
+ local whatsittracers = {
+ latelua = showdetails,
+ literal = showdetails,
+ }
+
+ callback.register("show_whatsit",function(n,l)
+ local s = nodes.whatsitcodes[n.subtype]
+ texio.write(" [" .. s .. "]")
+ local w = whatsittracers[s]
+ if w then
+ w(n,l)
+ end
+ end)
+
+end
diff --git a/tex/context/base/mkiv/driv-shp.mkiv b/tex/context/base/mkiv/driv-shp.mkiv
new file mode 100644
index 000000000..031d0265f
--- /dev/null
+++ b/tex/context/base/mkiv/driv-shp.mkiv
@@ -0,0 +1,28 @@
+%D \module
+%D [ file=driv-shp,
+%D version=2018.07.26,
+%D title=\CONTEXT\ Driver Macros,
+%D subtitle=Shipout,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\ifcase\contextlmtxmode\expandafter\endinput\fi
+
+\unprotect
+
+\registerctxluafile{driv-shp}{optimize}
+
+\registerctxluafile{back-lpd}{optimize}
+\registerctxluafile{back-lua}{optimize}
+\registerctxluafile{back-mps}{optimize}
+
+\appendtoks
+ \clf_enabledriver{pdf}% for now this way
+\to \everyjob
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/font-cff.lua b/tex/context/base/mkiv/font-cff.lua
index 75486624b..46deedb5f 100644
--- a/tex/context/base/mkiv/font-cff.lua
+++ b/tex/context/base/mkiv/font-cff.lua
@@ -1950,7 +1950,8 @@ end
-- 1,
-- 1
-- else
- local g, l = #globals, #locals
+ local g = #globals
+ local l = #locals
return
((g < 1240 and 107) or (g < 33900 and 1131) or 32768) + 1,
((l < 1240 and 107) or (l < 33900 and 1131) or 32768) + 1
diff --git a/tex/context/base/mkiv/font-cft.lua b/tex/context/base/mkiv/font-cft.lua
index 2e1610f17..ee9ffa6a7 100644
--- a/tex/context/base/mkiv/font-cft.lua
+++ b/tex/context/base/mkiv/font-cft.lua
@@ -242,7 +242,6 @@ do
hasitalics = t_boolean,
autoitalicamount = t_float,
nostackmath = t_boolean,
- noglyphnames = t_boolean,
mode = t_string,
hasmath = t_boolean,
mathitalics = t_boolean,
diff --git a/tex/context/base/mkiv/font-con.lua b/tex/context/base/mkiv/font-con.lua
index 9f85ee208..93ce9f5da 100644
--- a/tex/context/base/mkiv/font-con.lua
+++ b/tex/context/base/mkiv/font-con.lua
@@ -547,7 +547,6 @@ function constructors.scale(tfmdata,specification)
local hasitalics = properties.hasitalics
local autoitalicamount = properties.autoitalicamount
local stackmath = not properties.nostackmath
- local nonames = properties.noglyphnames
local haskerns = properties.haskerns or properties.mode == "base" -- we can have afm in node mode
local hasligatures = properties.hasligatures or properties.mode == "base" -- we can have afm in node mode
local realdimensions = properties.realdimensions
@@ -677,9 +676,10 @@ function constructors.scale(tfmdata,specification)
description = descriptions[unicode] or character
index = description.index or unicode
end
- local width = description.width
- local height = description.height
- local depth = description.depth
+ local width = description.width
+ local height = description.height
+ local depth = description.depth
+ local isunicode = description.unicode
if realdimensions then
-- this is mostly for checking issues
if not height or height == 0 then
@@ -706,16 +706,16 @@ function constructors.scale(tfmdata,specification)
-- if depth then depth = vdelta*depth else depth = scaleddepth end
if depth and depth ~= 0 then
depth = delta*depth
- if nonames then
+ if isunicode then
chr = {
- index = index,
- height = height,
- depth = depth,
- width = width,
+ index = index,
+ height = height,
+ depth = depth,
+ width = width,
+ unicode = isunicode,
}
else
chr = {
- name = description.name,
index = index,
height = height,
depth = depth,
@@ -723,36 +723,23 @@ function constructors.scale(tfmdata,specification)
}
end
else
- -- this saves a little bit of memory time and memory, esp for big cjk fonts
- if nonames then
+ if isunicode then
chr = {
- index = index,
- height = height,
- width = width,
+ index = index,
+ height = height,
+ width = width,
+ unicode = isunicode,
}
else
chr = {
- name = description.name,
index = index,
height = height,
width = width,
}
end
end
- local isunicode = description.unicode
if addtounicode then
- if isunicode then
- chr.unicode = isunicode
- chr.tounicode = tounicode(isunicode)
- -- in luatex > 0.85 we can do this:
- -- chr.tounicode = isunicode
- else
- chr.tounicode = unknowncode
- end
- else
- if isunicode then
- chr.unicode = isunicode
- end
+ chr.tounicode = isunicode and tounicode(isunicode) or unknowncode
end
if hasquality then
-- we could move these calculations elsewhere (saves calculations)
@@ -827,7 +814,10 @@ function constructors.scale(tfmdata,specification)
if stackmath then
local mk = character.mathkerns
if mk then
- local tr, tl, br, bl = mk.topright, mk.topleft, mk.bottomright, mk.bottomleft
+ local tr = mk.topright
+ local tl = mk.topleft
+ local br = mk.bottomright
+ local bl = mk.bottomleft
chr.mathkern = { -- singular -> should be patched in luatex !
top_right = tr and mathkerns(tr,vdelta) or nil,
top_left = tl and mathkerns(tl,vdelta) or nil,
@@ -1174,7 +1164,9 @@ loose our testcases for <l n='luatex'/>.</p>
--ldx]]--
function constructors.hashinstance(specification,force)
- local hash, size, fallbacks = specification.hash, specification.size, specification.fallbacks
+ local hash = specification.hash
+ local size = specification.size
+ local fallbacks = specification.fallbacks
if force or not hash then
hash = constructors.hashfeatures(specification)
specification.hash = hash
@@ -1612,7 +1604,8 @@ end
-- while typesetting
function constructors.collectprocessors(what,tfmdata,features,trace,report)
- local processes, nofprocesses = { }, 0
+ local processes = { }
+ local nofprocesses = 0
if features and next(features) then
local properties = tfmdata.properties
local whathandler = handlers[what]
diff --git a/tex/context/base/mkiv/font-ctx.lua b/tex/context/base/mkiv/font-ctx.lua
index 98825c3b6..6847a2b8d 100644
--- a/tex/context/base/mkiv/font-ctx.lua
+++ b/tex/context/base/mkiv/font-ctx.lua
@@ -793,7 +793,8 @@ end
local function registercontext(fontnumber,extraname,option)
local extra = setups[extraname]
if extra then
- local mergedfeatures, mergedname = { }, nil
+ local mergedfeatures = { }
+ local mergedname = nil
if option < 0 then
mergedname = fontnumber .. "-" .. extraname
else
@@ -3297,7 +3298,8 @@ function fonts.helpers.collectanchors(tfmdata)
a[target] = { anchor }
return
end
- local x, y = anchor[1], anchor[2]
+ local x = anchor[1]
+ local y = anchor[2]
for k, v in next, t do
if v[1] == x and v[2] == y then
return
diff --git a/tex/context/base/mkiv/font-dsp.lua b/tex/context/base/mkiv/font-dsp.lua
index c5fb14d46..f8bf6f2c8 100644
--- a/tex/context/base/mkiv/font-dsp.lua
+++ b/tex/context/base/mkiv/font-dsp.lua
@@ -3502,14 +3502,15 @@ function readers.avar(f,fontdata,specification)
local lastfrom = false
local lastto = false
for i=1,nofvalues do
- local f, t = read2dot14(f), read2dot14(f)
- if lastfrom and f <= lastfrom then
+ local from = read2dot14(f)
+ local to = read2dot14(f)
+ if lastfrom and from <= lastfrom then
-- ignore
- elseif lastto and t >= lastto then
+ elseif lastto and to >= lastto then
-- ignore
else
- values[#values+1] = { f, t }
- lastfrom, lastto = f, t
+ values[#values+1] = { from, to }
+ lastfrom, lastto = from, to
end
end
nofvalues = #values
diff --git a/tex/context/base/mkiv/font-fbk.lua b/tex/context/base/mkiv/font-fbk.lua
index cf500d0ce..122e43ddc 100644
--- a/tex/context/base/mkiv/font-fbk.lua
+++ b/tex/context/base/mkiv/font-fbk.lua
@@ -115,9 +115,15 @@ local function composecharacters(tfmdata)
local ab = descriptions[acc].boundingbox
-- todo: adapt height
if cb and ab then
- local c_llx, c_lly, c_urx, c_ury = scale*cb[1], scale*cb[2], scale*cb[3], scale*cb[4]
- local a_llx, a_lly, a_urx, a_ury = scale*ab[1], scale*ab[2], scale*ab[3], scale*ab[4]
- local done = false
+ local c_llx = scale*cb[1]
+ local c_lly = scale*cb[2]
+ local c_urx = scale*cb[3]
+ local c_ury = scale*cb[4]
+ local a_llx = scale*ab[1]
+ local a_lly = scale*ab[2]
+ local a_urx = scale*ab[3]
+ local a_ury = scale*ab[4]
+ local done = false
if compose then
local i_compose = compose[i]
local i_anchored = i_compose and i_compose.anchored
diff --git a/tex/context/base/mkiv/font-fil.mkvi b/tex/context/base/mkiv/font-fil.mkvi
index ff6a46d73..ae83ef4c4 100644
--- a/tex/context/base/mkiv/font-fil.mkvi
+++ b/tex/context/base/mkiv/font-fil.mkvi
@@ -85,33 +85,53 @@
\expandafter\font_basics_define_font_synonym_yes
\fi}
-\def\font_basics_define_font_synonym_nop
+\unexpanded\def\font_basics_define_font_synonym_nop
{\expandafter\let\csname\??fontfile\m_font_name\endcsname\m_font_file
\doifelsenextoptionalcs\font_basics_define_font_synonym_nop_opt\font_basics_define_font_synonym_nop_nil}
-\def\font_basics_define_font_synonym_yes
+\unexpanded\def\font_basics_define_font_synonym_yes
{\expandafter\let\csname\??fontfile\fontclass\m_font_name\endcsname\m_font_file
\doifelsenextoptionalcs\font_basics_define_font_synonym_yes_opt\font_basics_define_font_synonym_yes_nil}
-\def\font_basics_define_font_synonym_nop_opt[#specification]%
+\unexpanded\def\edefinefontsynonym[#name]#crap[#file]%
+ {\edef\m_font_name{#name}%
+ \edef\m_font_file{#file}%
+ \ifx\fontclass\empty
+ \expandafter\font_basics_define_font_synonym_nop_expanded
+ \else
+ \expandafter\font_basics_define_font_synonym_yes_expanded
+ \fi}
+
+\unexpanded\def\font_basics_define_font_synonym_nop_expanded#crap[#spec]%
+ {\expandafter\let\csname\??fontfile\m_font_name\endcsname\m_font_file
+ \normalexpanded{\font_basics_define_font_synonym_nop_opt[#1]}}
+
+\unexpanded\def\font_basics_define_font_synonym_yes_expanded#crap[#spec]%
+ {\expandafter\let\csname\??fontfile\fontclass\m_font_name\endcsname\m_font_file
+ \normalexpanded{\font_basics_define_font_synonym_yes_opt[#spec]}}
+
+\unexpanded\def\font_basics_define_font_synonym_nop_opt[#specification]%
{\let\p_features \undefined
\let\p_fallbacks \undefined
\let\p_goodies \undefined
\let\p_designsize\undefined
\expandafter\font_basics_get_font_parameter_nop#specification,]=,}
-\def\font_basics_define_font_synonym_yes_opt[#specification]%
+\unexpanded\def\font_basics_define_font_synonym_yes_opt[#specification]%
{\let\p_features \undefined
\let\p_fallbacks \undefined
\let\p_goodies \undefined
\let\p_designsize\undefined
\expandafter\font_basics_get_font_parameter_yes#specification,]=,}
+% todo: check if we can use \edef but then we need to protect \mathsizesuffix .. in fact that
+% can be default then: \let\mathsizesuffix\relax .. i need to play with it first
+
\def\font_basics_get_font_parameter_nop#key=#value,%
{\if]#key%
\font_basics_get_font_parameter_nop_finish
\else
- \expandafter\normaledef\csname p_#key\endcsname{#value}%
+ \expandafter\normaldef\csname p_#key\endcsname{#value}% % no edef as we need to keep \mathsizesuffix
\expandafter\font_basics_get_font_parameter_nop
\fi}
@@ -119,7 +139,7 @@
{\if]#key%
\font_basics_get_font_parameter_yes_finish
\else
- \expandafter\normaledef\csname p_#key\endcsname{#value}%
+ \expandafter\normaldef\csname p_#key\endcsname{#value}% % no edef as we need to keep \mathsizesuffix
\expandafter\font_basics_get_font_parameter_yes
\fi}
diff --git a/tex/context/base/mkiv/font-imp-quality.lua b/tex/context/base/mkiv/font-imp-quality.lua
index 224d8dc27..01f0afe63 100644
--- a/tex/context/base/mkiv/font-imp-quality.lua
+++ b/tex/context/base/mkiv/font-imp-quality.lua
@@ -451,9 +451,12 @@ local function initialize(tfmdata,value)
right = right,
}
for i, chr in next, tfmdata.characters do
- local v, pl, pr = vector[i], nil, nil
+ local v = vector[i]
+ local pl = nil
+ local pr = nil
if v then
- pl, pr = v[1], v[2]
+ pl = v[1]
+ pr = v[2]
else
local d = data[i]
if d then
@@ -461,13 +464,15 @@ local function initialize(tfmdata,value)
if not s then
-- sorry
elseif type(s) == "table" then
- local vl, vr = vector[s[1]], vector[s[#s]]
+ local vl = vector[s[1]]
+ local vr = vector[s[#s]]
if vl then pl = vl[1] end
if vr then pr = vr[2] end
else
v = vector[s]
if v then
- pl, pr = v[1], v[2]
+ pl = v[1]
+ pr = v[2]
end
end
end
diff --git a/tex/context/base/mkiv/font-lib.mkvi b/tex/context/base/mkiv/font-lib.mkvi
index 3cff81751..081ae0f38 100644
--- a/tex/context/base/mkiv/font-lib.mkvi
+++ b/tex/context/base/mkiv/font-lib.mkvi
@@ -50,6 +50,7 @@
\registerctxluafile{font-otc}{}
\registerctxluafile{font-oth}{}
\registerctxluafile{font-osd}{}
+% \doifelsefileexists{font-osm.lua}{\registerctxluafile{font-osm}{}}{}
\registerctxluafile{font-ocl}{}
% we use otf code for type one
diff --git a/tex/context/base/mkiv/font-map.lua b/tex/context/base/mkiv/font-map.lua
index 7dd538858..d931b822e 100644
--- a/tex/context/base/mkiv/font-map.lua
+++ b/tex/context/base/mkiv/font-map.lua
@@ -523,7 +523,8 @@ function mappings.addtounicode(data,filename,checklookups,forceligatures)
glyph.unicode = unicode
end
else
- local t, n = { }, 0
+ local t = { }
+ local n = 0
for l=1,nsplit do
local base = split[l]
local u = unicodes[base] or unicodevector[base] or contextvector[name]
diff --git a/tex/context/base/mkiv/font-mps.lua b/tex/context/base/mkiv/font-mps.lua
index 6d4da9059..895835958 100644
--- a/tex/context/base/mkiv/font-mps.lua
+++ b/tex/context/base/mkiv/font-mps.lua
@@ -109,9 +109,12 @@ function metapost.paths(d,xfactor,yfactor)
elseif operator =="q" then -- "quadraticto"
size = size + 1
-- first is always a moveto
- local l_x, l_y = xfactor*sequence[i-2], yfactor*sequence[i-1]
- local m_x, m_y = xfactor*sequence[i+1], yfactor*sequence[i+2]
- local r_x, r_y = xfactor*sequence[i+3], yfactor*sequence[i+4]
+ local l_x = xfactor*sequence[i-2]
+ local l_y = yfactor*sequence[i-1]
+ local m_x = xfactor*sequence[i+1]
+ local m_y = yfactor*sequence[i+2]
+ local r_x = xfactor*sequence[i+3]
+ local r_y = yfactor*sequence[i+4]
path[size] = f_curveto (
l_x + 2/3 * (m_x-l_x),
l_y + 2/3 * (m_y-l_y),
@@ -149,9 +152,12 @@ function metapost.paths(d,xfactor,yfactor)
size = size + 1
-- first is always a moveto
local prev = segments[i-1]
- local l_x, l_y = xfactor*prev[#prev-2], yfactor*prev[#prev-1]
- local m_x, m_y = xfactor*segment[1], yfactor*segment[2]
- local r_x, r_y = xfactor*segment[3], yfactor*segment[4]
+ local l_x = xfactor*prev[#prev-2]
+ local l_y = yfactor*prev[#prev-1]
+ local m_x = xfactor*segment[1]
+ local m_y = yfactor*segment[2]
+ local r_x = xfactor*segment[3]
+ local r_y = yfactor*segment[4]
path[size] = f_curveto (
l_x + 2/3 * (m_x-l_x),
l_y + 2/3 * (m_y-l_y),
@@ -208,7 +214,10 @@ function metapost.maxbounds(data,index,factor)
local boundingbox = glyph.boundingbox
local xmin, ymin, xmax, ymax
if not maxbounds then
- xmin, ymin, xmax, ymax = 0, 0, 0, 0
+ xmin = 0
+ ymin = 0
+ xmax = 0
+ ymax = 0
for i=1,#glyphs do
local d = glyphs[i]
if d then
diff --git a/tex/context/base/mkiv/font-nod.lua b/tex/context/base/mkiv/font-nod.lua
index 6beaef469..a0eb88a25 100644
--- a/tex/context/base/mkiv/font-nod.lua
+++ b/tex/context/base/mkiv/font-nod.lua
@@ -112,7 +112,8 @@ end
function char_tracers.collect(head,list,tag,n)
n = n or 0
- local ok, fn = false, nil
+ local ok = false
+ local fn = nil
while head do
local char, id = isglyph(head)
if char then
@@ -159,7 +160,8 @@ function char_tracers.equal(ta, tb)
return false
else
for i=1,#ta do
- local a, b = ta[i], tb[i]
+ local a = ta[i]
+ local b = tb[i]
-- if a[1] ~= b[1] or a[2] ~= b[2] or a[3] ~= b[3] then
if a[1] ~= b[1] or a[2] ~= b[2] then
return false
diff --git a/tex/context/base/mkiv/font-one.lua b/tex/context/base/mkiv/font-one.lua
index 48bf117fe..9b296cac5 100644
--- a/tex/context/base/mkiv/font-one.lua
+++ b/tex/context/base/mkiv/font-one.lua
@@ -86,14 +86,16 @@ function afm.load(filename)
local name = file.removesuffix(file.basename(filename))
local data = containers.read(afm.cache,name)
local attr = lfs.attributes(filename)
- local size, time = attr and attr.size or 0, attr and attr.modification or 0
+ local size = attr and attr.size or 0
+ local time = attr and attr.modification or 0
--
local pfbfile = file.replacesuffix(name,"pfb")
local pfbname = resolvers.findfile(pfbfile,"pfb") or ""
if pfbname == "" then
pfbname = resolvers.findfile(file.basename(pfbfile),"pfb") or ""
end
- local pfbsize, pfbtime = 0, 0
+ local pfbsize = 0
+ local pfbtime = 0
if pfbname ~= "" then
local attr = lfs.attributes(pfbname)
pfbsize = attr.size or 0
@@ -324,7 +326,8 @@ local addthem = function(rawdata,ligatures)
local one = descriptions[unicodes[ligname]]
if one then
for _, pair in next, ligdata do
- local two, three = unicodes[pair[1]], unicodes[pair[2]]
+ local two = unicodes[pair[1]]
+ local three = unicodes[pair[2]]
if two and three then
local ol = one.ligatures
if ol then
@@ -392,7 +395,7 @@ local function enhance_add_extra_kerns(rawdata) -- using shcodes is not robust h
if what then
for complex, simple in next, what do
complex = unicodes[complex]
- simple = unicodes[simple]
+ simple = unicodes[simple]
if complex and simple then
local complexdescription = descriptions[complex]
if complexdescription then -- optional
@@ -445,7 +448,8 @@ local function adddimensions(data) -- we need to normalize afm to otf i.e. index
for unicode, description in next, data.descriptions do
local bb = description.boundingbox
if bb then
- local ht, dp = bb[4], -bb[2]
+ local ht = bb[4]
+ local dp = -bb[2]
if ht == 0 or ht < 0 then
-- no need to set it and no negative heights, nil == 0
else
@@ -757,7 +761,7 @@ local function check_afm(specification,fullname)
if foundname == "" then
foundname = fonts.names.getfilename(fullname,"afm") or ""
end
- if foundname == "" and afm.autoprefixed then
+ if fullname and foundname == "" and afm.autoprefixed then
local encoding, shortname = match(fullname,"^(.-)%-(.*)$") -- context: encoding-name.*
if encoding and shortname and fonts.encodings.known[encoding] then
shortname = findbinfile(shortname,'afm') or "" -- just to be sure
diff --git a/tex/context/base/mkiv/font-osd.lua b/tex/context/base/mkiv/font-osd.lua
index 32d791b48..f51ae7bf7 100644
--- a/tex/context/base/mkiv/font-osd.lua
+++ b/tex/context/base/mkiv/font-osd.lua
@@ -615,6 +615,8 @@ local function initializedevanagi(tfmdata)
end
end
--
+ -- needs checking: this might be needed per instance ?
+ --
if script == "deva" then
sharedfeatures["dv04"] = true -- dv04_remove_joiners
elseif script == "dev2" then
@@ -689,7 +691,7 @@ local function initialize_one(font,attr) -- we need a proper hook into the datas
if not devanagaridata then
- devanagaridata = {
+ devanagaridata = {
reph = false,
vattu = false,
blwfcache = { },
@@ -1329,7 +1331,7 @@ end
function handlers.devanagari_remove_joiners(head,start,kind,lookupname,replacement)
local stop = getnext(start)
- local font = getfont(start)
+ local font = getfont(start) -- hm
local last = start
while stop do
local char = ischar(stop,font)
diff --git a/tex/context/base/mkiv/font-ota.lua b/tex/context/base/mkiv/font-ota.lua
index a0bf616e7..76c267a81 100644
--- a/tex/context/base/mkiv/font-ota.lua
+++ b/tex/context/base/mkiv/font-ota.lua
@@ -302,9 +302,9 @@ if not classifiers then
end
function methods.arab(head,font,attr)
- local first, last = nil, nil
- local c_first, c_last = nil, nil
- local current, done = head, false
+ local first, last, c_first, c_last
+ local current = head
+ local done = false
current = tonut(current)
while current do
local char, id = ischar(current,font)
diff --git a/tex/context/base/mkiv/font-otc.lua b/tex/context/base/mkiv/font-otc.lua
index 595778e34..a774a81c2 100644
--- a/tex/context/base/mkiv/font-otc.lua
+++ b/tex/context/base/mkiv/font-otc.lua
@@ -278,7 +278,8 @@ local function addfeature(data,feature,specifications)
if not nocheck and not description then
skip = skip + 1
elseif type(replacement) == "table" then
- local r, n = { }, 0
+ local r = { }
+ local n = 0
for i=1,#replacement do
local u = tounicode(replacement[i])
if nocheck or descriptions[u] then
diff --git a/tex/context/base/mkiv/font-otj.lua b/tex/context/base/mkiv/font-otj.lua
index df9756f4e..bb3038935 100644
--- a/tex/context/base/mkiv/font-otj.lua
+++ b/tex/context/base/mkiv/font-otj.lua
@@ -456,7 +456,8 @@ function injections.setmove(current,factor,rlmode,x,injection)
end
function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk,checkmark) -- ba=baseanchor, ma=markanchor
- local dx, dy = factor*(ba[1]-ma[1]), factor*(ba[2]-ma[2])
+ local dx = factor*(ba[1]-ma[1])
+ local dy = factor*(ba[2]-ma[2])
nofregisteredmarks = nofregisteredmarks + 1
if rlmode >= 0 then
dx = tfmbase.width - dx -- see later commented ox
diff --git a/tex/context/base/mkiv/font-otl.lua b/tex/context/base/mkiv/font-otl.lua
index df83dc968..6e0939e76 100644
--- a/tex/context/base/mkiv/font-otl.lua
+++ b/tex/context/base/mkiv/font-otl.lua
@@ -495,7 +495,6 @@ local function copytotfm(data,cache_id)
properties.space = spacer
properties.encodingbytes = 2
properties.format = data.format or formats.otf
- properties.noglyphnames = true
properties.filename = filename
properties.fontname = fontname
properties.fullname = fullname
diff --git a/tex/context/base/mkiv/font-oto.lua b/tex/context/base/mkiv/font-oto.lua
index c32a7af25..6f6d89d43 100644
--- a/tex/context/base/mkiv/font-oto.lua
+++ b/tex/context/base/mkiv/font-oto.lua
@@ -49,7 +49,9 @@ local function gref(descriptions,n)
return f_unicode(n)
end
elseif n then
- local num, nam, j = { }, { }, 0
+ local num = { }
+ local nam = { }
+ local j = 0
for i=1,#n do
local ni = n[i]
if tonumber(ni) then -- first is likely a key
@@ -121,8 +123,8 @@ local basehash, basehashes, applied = { }, 1, { }
local function registerbasehash(tfmdata)
local properties = tfmdata.properties
- local hash = concat(applied," ")
- local base = basehash[hash]
+ local hash = concat(applied," ")
+ local base = basehash[hash]
if not base then
basehashes = basehashes + 1
base = basehashes
@@ -310,13 +312,16 @@ local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplis
for i=1,nofligatures do
local ligature = ligatures[i]
- local unicode, tree = ligature[1], ligature[2]
+ local unicode = ligature[1]
+ local tree = ligature[2]
make_1(present,tree,"ctx_"..unicode)
end
for i=1,nofligatures do
- local ligature = ligatures[i]
- local unicode, tree, lookupname = ligature[1], ligature[2], ligature[3]
+ local ligature = ligatures[i]
+ local unicode = ligature[1]
+ local tree = ligature[2]
+ local lookupname = ligature[3]
make_2(present,tfmdata,characters,tree,"ctx_"..unicode,unicode,unicode,done,sequence)
end
diff --git a/tex/context/base/mkiv/font-otr.lua b/tex/context/base/mkiv/font-otr.lua
index c7ff6b726..e851c3157 100644
--- a/tex/context/base/mkiv/font-otr.lua
+++ b/tex/context/base/mkiv/font-otr.lua
@@ -74,7 +74,6 @@ local lpegmatch = lpeg.match
local rshift = bit32.rshift
local setmetatableindex = table.setmetatableindex
-local formatters = string.formatters
local sortedkeys = table.sortedkeys
local sortedhash = table.sortedhash
local stripstring = string.nospaces
diff --git a/tex/context/base/mkiv/font-ots.lua b/tex/context/base/mkiv/font-ots.lua
index 4d011a934..b9f719a5f 100644
--- a/tex/context/base/mkiv/font-ots.lua
+++ b/tex/context/base/mkiv/font-ots.lua
@@ -829,7 +829,7 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature,rlmode,skip
end
end
if not match and not pre or not replace then
- local n = getnext(discfound)
+ local n = getnext(discfound)
local char = ischar(n,currentfont)
if char and ligature[char] then
match = true
@@ -841,8 +841,8 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature,rlmode,skip
local prev = getprev(start)
if stop then
setnext(stop)
- local tail = getprev(stop)
local copy = copy_node_list(start)
+ local tail = stop -- was: getprev(stop) -- Kai: needs checking on your samples
local liat = find_node_tail(copy)
if pre then
setlink(liat,pre)
@@ -939,7 +939,8 @@ function handlers.gpos_pair(head,start,dataset,sequence,kerns,rlmode,skiphash,st
end
local format = step.format
if format == "pair" then
- local a, b = krn[1], krn[2]
+ local a = krn[1]
+ local b = krn[2]
if a == true then
-- zero
elseif a then -- #a > 0
@@ -1559,7 +1560,8 @@ function chainprocs.gpos_pair(head,start,stop,dataset,sequence,currentlookup,rlm
end
local format = currentlookup.format
if format == "pair" then
- local a, b = krn[1], krn[2]
+ local a = krn[1]
+ local b = krn[2]
if a == true then
-- zero
elseif a then
@@ -3192,7 +3194,7 @@ local function testrun(disc,t_run,c_run,...)
local d = d_replace > d_post and d_replace or d_post
local head = getnext(disc) -- is: next
local tail = head
- for i=2,d do -- must start at 2 according to Kai
+ for i=2,d do -- must start at 2 according to Kai
local nx = getnext(tail)
local id = getid(nx)
if id == disc_code then
diff --git a/tex/context/base/mkiv/font-oup.lua b/tex/context/base/mkiv/font-oup.lua
index e7f483642..d1faadbf7 100644
--- a/tex/context/base/mkiv/font-oup.lua
+++ b/tex/context/base/mkiv/font-oup.lua
@@ -1466,7 +1466,9 @@ function readers.pack(data)
end
return false
elseif nt >= threshold then
- local one, two, rest = 0, 0, 0
+ local one = 0
+ local two = 0
+ local rest = 0
if pass == 1 then
for k,v in next, c do
if v == 1 then
diff --git a/tex/context/base/mkiv/font-shp.lua b/tex/context/base/mkiv/font-shp.lua
index 08eda9fdb..d5c194c85 100644
--- a/tex/context/base/mkiv/font-shp.lua
+++ b/tex/context/base/mkiv/font-shp.lua
@@ -389,9 +389,12 @@ local function segmentstopdf(segments,factor,bt,et)
elseif w == "q" then
local p = segments[i-1]
local n = #p
- local l_x, l_y = factor*p[n-2], factor*p[n-1]
- local m_x, m_y = factor*s[1], factor*s[2]
- local r_x, r_y = factor*s[3], factor*s[4]
+ local l_x = factor*p[n-2]
+ local l_y = factor*p[n-1]
+ local m_x = factor*s[1]
+ local m_y = factor*s[2]
+ local r_x = factor*s[3]
+ local r_y = factor*s[4]
m = m + 1
t[m] = f_c (
l_x + 2/3 * (m_x-l_x), l_y + 2/3 * (m_y-l_y),
diff --git a/tex/context/base/mkiv/font-sol.lua b/tex/context/base/mkiv/font-sol.lua
index c7bd5feca..002f9df13 100644
--- a/tex/context/base/mkiv/font-sol.lua
+++ b/tex/context/base/mkiv/font-sol.lua
@@ -348,8 +348,14 @@ directives.register("builders.paragraphs.solutions.splitters.encapsulate", funct
end)
function splitters.split(head) -- best also pass the direction
- local current, r2l, start, stop, attribute = head, false, nil, nil, 0
- cache, max_less, max_more = { }, 0, 0
+ local current = head
+ local r2l = false
+ local start = nil
+ local stop = nil
+ local attribute = 0
+ cache = { }
+ max_less = 0
+ max_more = 0
local function flush() -- we can move this
local font = getfont(start)
local last = getnext(stop)
@@ -445,12 +451,14 @@ function splitters.split(head) -- best also pass the direction
flush()
end
nofparagraphs = nofparagraphs + 1
- nofwords = nofwords + #cache
+ nofwords = nofwords + #cache
return head
end
local function collect_words(list) -- can be made faster for attributes
- local words, w, word = { }, 0, nil
+ local words = { }
+ local w = 0
+ local word = nil
if encapsulate then
for current, subtype in nextwhatsit, list do
if subtype == userdefinedwhatsit_code then -- hm
@@ -472,7 +480,8 @@ local function collect_words(list) -- can be made faster for attributes
end
end
else
- local current, first, last, index = list, nil, nil, nil
+ local first, last, index
+ local current = list
while current do
-- todo: disc and kern
local id = getid(current)
@@ -537,7 +546,9 @@ local function collect_words(list) -- can be made faster for attributes
if trace_split then
for i=1,#words do
local w = words[i]
- local n, f, l = w[1], w[2], w[3]
+ local n = w[1]
+ local f = w[2]
+ local l = w[3]
local c = cache[n]
if c then
report_splitters("found %4i: word %a, cached %a",n,nodes_to_utf(f,true,true,l),nodes_to_utf(c.original,true))
@@ -793,7 +804,8 @@ function splitters.optimize(head)
set, max = "less", max_less
end
-- we can keep the best variants
- local lastbest, lastbadness = nil, badness
+ local lastbest = nil
+ local lastbadness = badness
if preroll then
local bb, base
for i=1,max do
@@ -866,7 +878,7 @@ statistics.register("optimizer statistics", function()
if nofwords > 0 then
local elapsed = statistics.elapsedtime(splitters)
local average = noftries/elapsed
- return format("%s words identified in %s paragraphs, %s words retried, %s lines tried, %0.3f seconds used, %s adapted, %0.1f lines per second",
+ return format("%s words identified in %s paragraphs, %s words retried, %s lines tried, %s seconds used, %s adapted, %0.1f lines per second",
nofwords,nofparagraphs,noftries,nofadapted+nofkept,elapsed,nofadapted,average)
end
end)
diff --git a/tex/context/base/mkiv/font-syn.lua b/tex/context/base/mkiv/font-syn.lua
index 3951e8742..18c25fbfd 100644
--- a/tex/context/base/mkiv/font-syn.lua
+++ b/tex/context/base/mkiv/font-syn.lua
@@ -515,15 +515,20 @@ local function cleanname(name)
end
local function cleanfilename(fullname,defaultsuffix)
- local path, name, suffix = splitname(fullname)
- name = gsub(lower(name),"[^%a%d]","")
- if suffix and suffix ~= "" then
- return name .. ".".. suffix
- elseif defaultsuffix and defaultsuffix ~= "" then
- return name .. ".".. defaultsuffix
- else
- return name
+ if fullname then
+ local path, name, suffix = splitname(fullname)
+ if name then
+ name = gsub(lower(name),"[^%a%d]","")
+ if suffix and suffix ~= "" then
+ return name .. ".".. suffix
+ elseif defaultsuffix and defaultsuffix ~= "" then
+ return name .. ".".. defaultsuffix
+ else
+ return name
+ end
+ end
end
+ return "badfontname"
end
local sorter = function(a,b)
@@ -2009,7 +2014,8 @@ local lastlookups, lastpattern = { }, ""
local function look_them_up(lookups,specification)
for key, value in sortedhash(specification) do
- local t, n = { }, 0
+ local t = { }
+ local n = 0
if find(value,"*",1,true) then
value = topattern(value)
for i=1,#lookups do
diff --git a/tex/context/base/mkiv/font-tpk.lua b/tex/context/base/mkiv/font-tpk.lua
new file mode 100644
index 000000000..8f4b00b56
--- /dev/null
+++ b/tex/context/base/mkiv/font-tpk.lua
@@ -0,0 +1,1292 @@
+ if not modules then modules = { } end modules ['font-tpk'] = {
+ version = 1.001,
+ comment = "companion to font-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- The bitmap loader is more or less derived from the luatex version (taco)
+-- which is derived from pdftex (thanh) who uses code from dvips (thomas)
+-- adapted by piet ... etc. The tfm and vf readers are also derived from
+-- luatex. All do things a bit more luaish and errors are of course mine.
+
+local next = next
+local extract, band, lshift, rshift = bit32.extract, bit32.band, bit32.lshift, bit32.rshift
+local idiv = number.idiv
+local char = string.char
+local concat, insert, remove, copy = table.concat, table.insert, table.remove, table.copy
+local tobitstring = number.tobitstring
+local formatters = string.formatters
+local round = math.round
+
+local streams = utilities.streams
+local openstream = streams.open
+local streamsize = streams.size
+local readcardinal1 = streams.readcardinal1
+local readcardinal2 = streams.readcardinal2
+local readcardinal3 = streams.readcardinal3
+local readcardinal4 = streams.readcardinal4
+local readinteger1 = streams.readinteger1
+local readinteger2 = streams.readinteger2
+local readinteger3 = streams.readinteger3
+local readinteger4 = streams.readinteger4
+local readbyte = streams.readbyte
+local readbytes = streams.readbytes
+local readstring = streams.readstring
+local skipbytes = streams.skipbytes
+local getposition = streams.getposition
+local setposition = streams.setposition
+
+if not fonts then fonts = { handlers = { tfm = { } } } end
+
+local handlers = fonts.handlers
+local tfm = handlers.tfm or { }
+handlers.tfm = tfm
+local readers = tfm.readers or { }
+tfm.readers = readers
+
+tfm.version = 1.005
+tfm.cache = containers.define("fonts", "tfm", tfm.version, true)
+
+-- Performance is no real issue here so I didn't optimize too much. After
+-- all, these files are small and we mostly use opentype or type1 fonts.
+
+do
+
+ local function readbitmap(glyph,s,flagbyte)
+
+ local inputbyte = 0
+ local bitweight = 0
+ local dynf = 0
+ local remainder = 0
+ local realfunc = nil
+ local repeatcount = 0
+
+ local function getnyb() -- can be inlined
+ if bitweight == 0 then
+ bitweight = 16
+ inputbyte = readbyte(s)
+ return extract(inputbyte,4,4)
+ else
+ bitweight = 0
+ return band(inputbyte,15)
+ end
+ end
+
+ local function getbit() -- can be inlined
+ bitweight = rshift(bitweight,1)
+ if bitweight == 0 then -- actually we can check for 1
+ inputbyte = readbyte(s)
+ bitweight = 128
+ end
+ return band(inputbyte,bitweight)
+ end
+
+ local function pkpackednum()
+ local i = getnyb(s)
+ if i == 0 then
+ repeat
+ j = getnyb()
+ i = i + 1
+ until (j ~= 0)
+ if i > 3 then
+ return handlehuge(i,j)
+ else
+ for i=1,i do
+ j = j * 16 + getnyb()
+ end
+ return j - 15 + (13 - dynf) * 16 + dynf
+ end
+ elseif i <= dynf then
+ return i
+ elseif i < 14 then
+ return (i - dynf - 1) * 16 + getnyb() + dynf + 1
+ elseif i == 14 then
+ repeatcount = pkpackednum()
+ else
+ repeatcount = 1
+ end
+ return realfunc()
+ end
+
+ local function rest()
+ if remainder < 0 then
+ remainder = -remainder
+ return 0
+ elseif remainder > 4000 then
+ remainder = 4000 - remainder
+ return 4000
+ elseif remainder > 0 then
+ local i = remainder
+ remainder = 0
+ realfunc = pkpackednum
+ return i
+ else
+ -- error = "pk issue that shouldn't happen"
+ return 0
+ end
+ end
+
+ local function handlehuge(i,j)
+ while i ~= 0 do
+ j = lshift(j,4) + getnyb()
+ -- j = extract(j,8,4) + getnyb()
+ i = i - 1
+ end
+ remainder = j - 15 + (13 - dynf) * 16 + dynf
+ realfunc = rest
+ return rest()
+ end
+
+ local gpower = { [0] =
+ 0, 1, 3, 7, 15, 31, 63, 127,
+ 255, 511, 1023, 2047, 4095, 8191, 16383, 32767,
+ 65535
+ }
+
+ local raster = { }
+ local r = 0
+ glyph.stream = raster
+
+ local xsize = glyph.xsize
+ local ysize = glyph.ysize
+ local word = 0
+ local wordweight = 0
+ local wordwidth = idiv(xsize + 15,16)
+ local rowsleft = 0
+ local turnon = band(flagbyte,8) == 8 and true or false
+ local hbit = 0
+ local count = 0
+ --
+ realfunc = pkpackednum
+ dynf = idiv(flagbyte,16)
+ --
+ if dynf == 14 then
+ bitweight = 0
+ for i=1,ysize do
+ word = 0
+ wordweight = 32768
+ for j=1,xsize do
+ if getbit() ~= 0 then
+ word = word + wordweight
+ end
+ wordweight = rshift(wordweight,1)
+ if wordweight == 0 then
+ r = r + 1
+ raster[r] = word
+ word = 0
+ wordweight = 32768
+ end
+ end
+ if wordweight ~= 32768 then
+ r = r + 1
+ raster[r] = word
+ end
+ end
+ else
+ rowsleft = ysize
+ hbit = xsize
+ repeatcount = 0
+ wordweight = 16
+ word = 0
+ bitweight = 0
+ while rowsleft > 0 do
+ count = realfunc()
+ while count ~= 0 do
+ if count < wordweight and count < hbit then
+ if turnon then
+ word = word + gpower[wordweight] - gpower[wordweight - count]
+ end
+ hbit = hbit - count
+ wordweight = wordweight - count
+ count = 0
+ elseif count >= hbit and hbit <= wordweight then
+ if turnon then
+ word = word + gpower[wordweight] - gpower[wordweight - hbit]
+ end
+ r = r + 1
+ raster[r] = word
+ for i=1,repeatcount*wordwidth do
+ r = r + 1
+ raster[r] = raster[r - wordwidth]
+ end
+ rowsleft = rowsleft - repeatcount - 1
+ repeatcount = 0
+ word = 0
+ wordweight = 16
+ count = count - hbit
+ hbit = xsize
+ else
+ if turnon then
+ word = word + gpower[wordweight]
+ end
+ r = r + 1
+ raster[r] = word
+ word = 0
+ count = count - wordweight
+ hbit = hbit - wordweight
+ wordweight = 16
+ end
+ end
+ turnon = not turnon
+ end
+ if rowsleft ~= 0 or hbit ~= xsize then
+ print("ERROR",rowsleft,hbit,xsize)
+ -- error = "error while unpacking, more bits than required"
+ end
+ end
+
+ end
+
+ function readers.showpk(glyph)
+ local xsize = glyph.xsize
+ local ysize = glyph.ysize
+ local stream = glyph.stream
+ local result = { }
+ local rr = { }
+ local r = 0
+ local s = 0
+ local cw = idiv(xsize+ 7, 8)
+ local rw = idiv(xsize+15,16)
+ local extra = 2 * rw == cw
+ local b
+ for y=1,ysize do
+ r = 0
+ for x=1,rw-1 do
+ s = s + 1 ; b = stream[s]
+ r = r + 1 ; rr[r] = tobitstring(b,16,16)
+ end
+ s = s + 1 ; b = stream[s]
+ if extra then
+ r = r + 1 ; rr[r] = tobitstring(b,16,16)
+ else
+ r = r + 1 ; rr[r] = tobitstring(extract(b,8+(8-cw),cw),cw,cw)
+ end
+ result[y] = concat(rr)
+ end
+ return concat(result,"\n")
+ end
+
+ local template = formatters [ [[
+ %.3N 0 %i %i %i %i d1
+ q
+ %i 0 0 %i %i %i cm
+ BI
+ /W %i
+ /H %i
+ /IM true
+ /BPC 1
+ /D [1 0]
+ ID %t
+ EI
+ Q]] ]
+
+ function readers.pktopdf(glyph,width)
+ local xsize = glyph.xsize or 0
+ local ysize = glyph.ysize or 0
+ local xoffset = glyph.xoffset or 0
+ local yoffset = glyph.yoffset or 0
+ local stream = glyph.stream
+
+ local dpi = 1
+ local newdpi = 1
+
+ local xdpi = dpi * xsize / newdpi
+ local ydpi = dpi * ysize / newdpi
+
+ local llx = - xoffset
+ local lly = yoffset - ysize + 1
+ local urx = llx + xsize + 1
+ local ury = lly + ysize
+
+ local result = { }
+ local r = 0
+ local s = 0
+ local cw = idiv(xsize+ 7, 8)
+ local rw = idiv(xsize+15,16)
+ local extra = 2 * rw == cw
+ local b
+ for y=1,ysize do
+ for x=1,rw-1 do
+ s = s + 1 ; b = stream[s]
+ r = r + 1 ; result[r] = char(extract(b,8,8),extract(b,0,8))
+ end
+ s = s + 1 ; b = stream[s]
+ if extra then
+ r = r + 1 ; result[r] = char(extract(b,8,8),extract(b,0,8))
+ else
+ r = r + 1 ; result[r] = char(extract(b,8,8))
+ end
+ end
+ return
+ template(width,llx,lly,urx,ury,xdpi,ydpi,llx,lly,xsize,ysize,result),
+ llx, lly, urx, ury
+ end
+
+ function readers.loadpk(filename)
+ local s = openstream(filename)
+ local preamble = readcardinal1(s)
+ local version = readcardinal1(s)
+ local comment = readstring(s,readcardinal1(s))
+ local designsize = readcardinal4(s)
+ local checksum = readcardinal4(s)
+ local hppp = readcardinal4(s)
+ local vppp = readcardinal4(s)
+ if preamble ~= 247 or version ~= 89 or not vppp then
+ return { error = "invalid preamble" }
+ end
+ local glyphs = { }
+ local data = {
+ designsize = designsize,
+ comment = comment,
+ hppp = hppp,
+ vppp = vppp,
+ glyphs = glyphs,
+ }
+ while true do
+ local flagbyte = readcardinal1(s)
+ if flagbyte < 240 then
+ local c = band(flagbyte,7)
+ local length, index, width, pixels, xsize, ysize, xoffset, yoffset
+ if c >= 0 and c <= 3 then
+ length = band(flagbyte,7) * 256 + readcardinal1(s) - 3
+ index = readcardinal1(s)
+ width = readinteger3(s)
+ pixels = readcardinal1(s)
+ xsize = readcardinal1(s)
+ ysize = readcardinal1(s)
+ xoffset = readcardinal1(s)
+ yoffset = readcardinal1(s)
+ if xoffset > 127 then
+ xoffset = xoffset - 256
+ end
+ if yoffset > 127 then
+ yoffset = yoffset - 256
+ end
+ elseif c >= 4 and c <= 6 then
+ length = band(flagbyte,3) * 65536 + readcardinal1(s) * 256 + readcardinal1(s) - 4
+ index = readcardinal1(s)
+ width = readinteger3(s)
+ pixels = readcardinal2(s)
+ xsize = readcardinal2(s)
+ ysize = readcardinal2(s)
+ xoffset = readcardinal2(s)
+ yoffset = readcardinal2(s)
+ else -- 7
+ length = readcardinal4(s) - 9
+ index = readcardinal4(s)
+ width = readinteger4(s)
+ pixels = readcardinal4(s)
+ readcardinal4(s)
+ xsize = readcardinal4(s)
+ ysize = readcardinal4(s)
+ xoffset = readcardinal4(s)
+ yoffset = readcardinal4(s)
+ end
+ local glyph = {
+ index = index,
+ width = width,
+ pixels = pixels,
+ xsize = xsize,
+ ysize = ysize,
+ xoffset = xoffset,
+ yoffset = yoffset,
+ }
+ if length <= 0 then
+ data.error = "bad packet"
+ return data
+ end
+ readbitmap(glyph,s,flagbyte)
+ glyphs[index] = glyph
+ elseif flagbyte == 240 then
+ -- k[1] x[k]
+ skipbytes(s,readcardinal1(s))
+ elseif flagbyte == 241 then
+ -- k[2] x[k]
+ skipbytes(s,readcardinal2(s)*2)
+ elseif flagbyte == 242 then
+ -- k[3] x[k]
+ skipbytes(s,readcardinal3(s)*3)
+ elseif flagbyte == 243 then
+ -- k[4] x[k]
+ skipbytes(s,readcardinal4(s)*4) -- readinteger4
+ elseif flagbyte == 244 then
+ -- y[4]
+ skipbytes(s,4)
+ elseif flagbyte == 245 then
+ break
+ elseif flagbyte == 246 then
+ -- nop
+ else
+ data.error = "unknown pk command"
+ break
+ end
+ end
+ return data
+ end
+
+end
+
+do
+
+ local leftboundary = -1
+ local rightboundary = -2
+ local boundarychar = 65536
+
+ function readers.loadtfm(filename)
+ local data
+ --
+ local function someerror(m)
+ if not data then
+ data = { }
+ end
+ data.error = m or "fatal error"
+ return data
+ end
+ --
+ local s = openstream(filename)
+ if not s then
+ return someerror()
+ end
+ --
+ local wide = false
+ local header = 0
+ local max = 0
+ local size = streamsize(s)
+ local glyphs = table.setmetatableindex(function(t,k) local v = { } t[k] = v return v end)
+ local parameters = { }
+ local direction = 0
+ --
+ local lf, lh, bc, ec, nw, nh, nd, ni, nl, nk, ne, np
+ --
+ lf = readcardinal2(s)
+ if lf ~= 0 then
+ header = 6
+ max = 255
+ wide = false
+ lh = readcardinal2(s)
+ bc = readcardinal2(s)
+ ec = readcardinal2(s)
+ nw = readcardinal2(s)
+ nh = readcardinal2(s)
+ nd = readcardinal2(s)
+ ni = readcardinal2(s)
+ nl = readcardinal2(s)
+ nk = readcardinal2(s)
+ ne = readcardinal2(s)
+ np = readcardinal2(s)
+ else
+ header = 14
+ max = 65535
+ wide = readcardinal4(s) == 0
+ if not wide then
+ return someerror("invalid format")
+ end
+ lf = readcardinal4(s)
+ lh = readcardinal4(s)
+ bc = readcardinal4(s)
+ ec = readcardinal4(s)
+ nw = readcardinal4(s)
+ nh = readcardinal4(s)
+ nd = readcardinal4(s)
+ ni = readcardinal4(s)
+ nl = readcardinal4(s)
+ nk = readcardinal4(s)
+ ne = readcardinal4(s)
+ np = readcardinal4(s)
+ direction = readcardinal4(s)
+ end
+ if (bc > ec + 1) or (ec > max) then
+ return someerror("file is too small")
+ end
+ if bc > max then
+ bc, ec = 1, 0
+ end
+ local nlw = (wide and 2 or 1) * nl
+ local neew = (wide and 2 or 1) * ne
+ local ncw = (wide and 2 or 1) * (ec - bc + 1)
+ if lf ~= (header + lh + ncw + nw + nh + nd + ni + nlw + nk + neew + np) then
+ return someerror("file is too small")
+ end
+ if nw == 0 or nh == 0 or nd == 0 or ni == 0 then
+ return someerror("no glyphs")
+ end
+ if lf * 4 > size then
+ return someerror("file is too small")
+ end
+ local slh = lh
+ if lh < 2 then
+ return someerror("file is too small")
+ end
+ local checksum = readcardinal4(s)
+ local designsize = readcardinal2(s)
+ designsize = designsize * 256 + readcardinal1(s)
+ designsize = designsize * 16 + rshift(readcardinal1(s),4)
+ if designsize < 0xFFFF then
+ return someerror("weird designsize")
+ end
+ --
+ local alpha = 16
+ local z = designsize
+ while z >= 040000000 do
+ z = rshift(z,1)
+ alpha = alpha + alpha
+ end
+ local beta = idiv(256,alpha)
+ alpha = alpha * z
+ --
+ local function readscaled()
+ local a, b, c, d = readbytes(s,4)
+ local n = idiv(rshift(rshift(d*z,8)+c*z,8)+b*z,beta)
+ if a == 0 then
+ return n
+ elseif a == 255 then
+ return n - alpha
+ else
+ return 0
+ end
+ end
+ --
+ local function readunscaled()
+ local a, b, c, d = readbytes(s,4)
+ if a > 127 then
+ a = a - 256
+ end
+ return a * 0xFFFFF + b * 0xFFF + c * 0xF + rshift(d,4)
+ end
+ --
+ while lh > 2 do -- can be one-liner
+ skipbytes(s,4)
+ lh = lh - 1
+ end
+ local saved = getposition(s)
+ setposition(s,(header + slh + ncw) * 4 + 1)
+ local widths = { } for i=0,nw-1 do widths [i] = readscaled() end
+ local heights = { } for i=0,nh-1 do heights[i] = readscaled() end
+ local depths = { } for i=0,nd-1 do depths [i] = readscaled() end
+ local italics = { } for i=0,ni-1 do italics[i] = readscaled() end
+ if widths[0] ~= 0 or heights[0] ~= 0 or depths[0] ~= 0 then
+ return someerror("invalid dimensions")
+ end
+ --
+ local blabel = nl
+ local bchar = boundarychar
+ --
+ local ligatures = { }
+ if nl > 0 then
+ for i=0,nl-1 do
+ local a, b, c, d = readbytes(s,4)
+ ligatures[i] = {
+ skip = a,
+ nxt = b,
+ op = c,
+ rem = d,
+ }
+ if a > 128 then
+ if 256 * c + d >= nl then
+ return someerror("invalid ligature table")
+ end
+ if a == 255 and i == 0 then
+ bchar = b
+ end
+ else
+ if c < 128 then
+ -- whatever
+ elseif 256 * (c - 128) + d >= nk then
+ return someerror("invalid ligature table")
+ end
+ if (a < 128) and (i - 0 + a + 1 >= nl) then
+ return someerror("invalid ligature table")
+ end
+ end
+ if a == 255 then
+ blabel = 256 * c + d
+ end
+ end
+ end
+ local allkerns = { }
+ for i=0,nk-1 do
+ allkerns[i] = readscaled()
+ end
+ local extensibles = { }
+ for i=0,ne-1 do
+ extensibles[i] = wide and {
+ top = readcardinal2(s),
+ bot = readcardinal2(s),
+ mid = readcardinal2(s),
+ rep = readcardinal2(s),
+ } or {
+ top = readcardinal1(s),
+ bot = readcardinal1(s),
+ mid = readcardinal1(s),
+ rep = readcardinal1(s),
+ }
+ end
+ for i=1,np do
+ if i == 1 then
+ parameters[i] = readunscaled()
+ else
+ parameters[i] = readscaled()
+ end
+ end
+ for i=1,7 do
+ if not parameters[i] then
+ parameters[i] = 0
+ end
+ end
+ --
+ setposition(s,saved)
+ local extras = false
+ if blabel ~= nl then
+ local k = blabel
+ while true do
+ local l = ligatures[k]
+ local skip = l.skip
+ if skip <= 128 then
+ -- if l.op >= 128 then
+ -- extras = true -- kern
+ -- else
+ extras = true -- ligature
+ -- end
+ end
+ if skip == 0 then
+ k = k + 1
+ else
+ if skip >= 128 then
+ break
+ end
+ k = k + skip + 1
+ end
+ end
+ end
+ if extras then
+ local ligas = { }
+ local kerns = { }
+ local k = blabel
+ while true do
+ local l = ligatures[k]
+ local skip = l.skip
+ if skip <= 128 then
+ local nxt = l.nxt
+ local op = l.op
+ local rem = l.rem
+ if op >= 128 then
+ kerns[nxt] = allkerns[256 * (op - 128) + rem]
+ else
+ ligas[nxt] = { type = op * 2 + 1, char = rem }
+ end
+ end
+ if skip == 0 then
+ k = k + 1
+ else
+ if skip >= 128 then
+ break;
+ end
+ k = k + skip + 1
+ end
+ end
+ if next(kerns) then
+ local glyph = glyphs[leftboundary]
+ glyph.kerns = kerns
+ glyph.remainder = 0
+ end
+ if next(ligas) then
+ local glyph = glyphs[leftboundary]
+ glyph.ligatures = ligas
+ glyph.remainder = 0
+ end
+ end
+ for i=bc,ec do
+ local glyph, width, height, depth, italic, tag, remainder
+ if wide then
+ width = readcardinal2(s)
+ height = readcardinal1(s)
+ depth = readcardinal1(s)
+ italic = readcardinal1(s)
+ tag = readcardinal1(s)
+ remainder = readcardinal2(s)
+ else
+ width = readcardinal1(s)
+ height = readcardinal1(s)
+ depth = extract(height,0,4)
+ height = extract(height,4,4)
+ italic = readcardinal1(s)
+ tag = extract(italic,0,2)
+ italic = extract(italic,2,6)
+ remainder = readcardinal1(s)
+ end
+ if width == 0 then
+ -- nothing
+ else
+ if width >= nw or height >= nh or depth >= nd or italic >= ni then
+ return someerror("invalid dimension index")
+ end
+ local extensible, nextinsize
+ if tag == 0 then
+ -- nothing special
+ else
+ local r = remainder
+ if tag == 1 then
+ if r >= nl then
+ return someerror("invalid ligature index")
+ end
+ elseif tag == 2 then
+ if r < bc or r > ec then
+ return someerror("invalid chain index")
+ end
+ while r < i do
+ local g = glyphs[r]
+ if g.tag ~= list_tag then
+ break
+ end
+ r = g.remainder
+ end
+ if r == i then
+ return someerror("cycles in chain")
+ end
+ nextinsize = r
+ elseif tag == 3 then
+ if r >= ne then
+ return someerror("bad extensible")
+ end
+ extensible = extensibles[r] -- remainder ?
+ remainder = 0
+ end
+ end
+ glyphs[i] = {
+ width = widths [width],
+ height = heights[height],
+ depth = depths [depth],
+ italic = italics[italic],
+ tag = tag,
+ -- index = i,
+ remainder = remainder,
+ extensible = extensible,
+ next = nextinsize,
+ }
+ end
+ end
+ for i=bc,ec do
+ local glyph = glyphs[i]
+ if glyph.tag == 1 then
+ -- ligature
+ local k = glyph.remainder
+ local l = ligatures[k]
+ if l.skip > 128 then
+ k = 256 * l.op + l.rem
+ end
+ local ligas = { }
+ local kerns = { }
+ while true do
+ local l = ligatures[k]
+ local skip = l.skip
+ if skip <= 128 then
+ local nxt = l.nxt
+ local op = l.op
+ local rem = l.rem
+ if op >= 128 then
+ local kern = allkerns[256 * (op - 128) + rem]
+ if nxt == bchar then
+ kerns[rightboundary] = kern
+ end
+ kerns[nxt] = kern
+ else
+ local ligature = { type = op * 2 + 1, char = rem }
+ if nxt == bchar then
+ ligas[rightboundary] = ligature
+ end
+ ligas[nxt] = ligature -- shared
+ end
+ end
+ if skip == 0 then
+ k = k + 1
+ else
+ if skip >= 128 then
+ break
+ end
+ k = k + skip + 1
+ end
+ end
+ if next(kerns)then
+ glyph.kerns = kerns
+ glyph.remainder = 0
+ end
+ if next(ligas) then
+ glyph.ligatures = ligas
+ glyph.remainder = 0
+ end
+ end
+ end
+ --
+ if bchar ~= boundarychar then
+ glyphs[rightboundary] = copy(glyphs[bchar])
+ end
+ --
+ -- for k, v in next, glyphs do
+ -- v.tag = nil
+ -- v.remainder = nil
+ -- end
+ --
+ return {
+ name = file.nameonly(filename),
+ fontarea = file.pathpart(filename),
+ glyphs = glyphs,
+ parameters = parameters,
+ designsize = designsize,
+ size = designsize,
+ direction = direction,
+ -- checksum = checksum,
+ -- embedding = "unknown",
+ -- encodingbytes = 0,
+ -- extend = 1000,
+ -- slant = 0,
+ -- squeeze = 0,
+ -- format = "unknown",
+ -- identity = "unknown",
+ -- mode = 0,
+ -- streamprovider = 0,
+ -- tounicode = 0,
+ -- type = "unknown",
+ -- units_per_em = 0,
+ -- used = false,
+ -- width = 0,
+ -- writingmode = "unknown",
+ }
+ end
+
+end
+
+do
+
+ local push = { "push" }
+ local push = { "pop" }
+
+ local w, x, y, z, f
+ local stack
+ local s, result, r
+ local alpha, beta, z
+
+ local function scaled1()
+ local a = readbytes(s,1)
+ if a == 0 then
+ return 0
+ elseif a == 255 then
+ return - alpha
+ else
+ return 0 -- error
+ end
+ end
+
+ local function scaled2()
+ local a, b = readbytes(s,2)
+ local sw = idiv(b*z,beta)
+ if a == 0 then
+ return sw
+ elseif a == 255 then
+ return sw - alpha
+ else
+ return 0 -- error
+ end
+ end
+
+ local function scaled3()
+ local a, b, c = readbytes(s,3)
+ local sw = idiv(rshift(c*z,8)+b*z,beta)
+ if a == 0 then
+ return sw
+ elseif a == 255 then
+ return sw - alpha
+ else
+ return 0 -- error
+ end
+ end
+
+ local function scaled4()
+ local a, b, c, d = readbytes(s,4)
+ local sw = idiv( rshift(rshift(d*z,8)+(c*z),8)+b*z,beta)
+ if a == 0 then
+ return sw
+ elseif a == 255 then
+ return sw - alpha
+ else
+ return 0 -- error
+ end
+ end
+
+ local function dummy()
+ end
+
+ local actions = {
+
+ [128] = function() r = r + 1 result[r] = { "slot", f or 1, readcardinal1(s) } p = p + 1 end,
+ [129] = function() r = r + 1 result[r] = { "slot", f or 1, readcardinal2(s) } p = p + 2 end,
+ [130] = function() r = r + 1 result[r] = { "slot", f or 1, readcardinal3(s) } p = p + 3 end,
+ [131] = function() r = r + 1 result[r] = { "slot", f or 1, readcardinal4(s) } p = p + 4 end,
+
+ [132] = function()
+ r = r + 1
+ result[r] = { "rule", scaled4(), scaled4() }
+ p = p + 8
+ end,
+
+ [133] = function()
+ r = r + 1 result[r] = push
+ r = r + 1 result[r] = { "slot", f or 1, readcardinal1(s) }
+ r = r + 1 result[r] = pop
+ p = p + 1
+ end,
+ [134] = function()
+ r = r + 1 result[r] = push
+ r = r + 1 result[r] = { "slot", f or 1, readcardinal2(s) }
+ r = r + 1 result[r] = pop
+ p = p + 2
+ end,
+ [135] = function()
+ r = r + 1 result[r] = push
+ r = r + 1 result[r] = { "slot", f or 1, readcardinal2(s) }
+ r = r + 1 result[r] = pop
+ p = p + 3
+ end,
+ [136] = function()
+ r = r + 1 result[r] = push
+ r = r + 1 result[r] = { "slot", f or 1, readcardinal4(s) }
+ r = r + 1 result[r] = pop
+ p = p + 4
+ end,
+
+ [137] = function()
+ r = r + 1 result[r] = push
+ r = r + 1 result[r] = { "rule", scaled4(), scaled4() }
+ r = r + 1 result[r] = pop
+ p = p + 8
+ end,
+
+ [138] = dummy, -- nop
+ [139] = dummy, -- bop
+ [140] = dummy, -- eop
+
+ [141] = function()
+ insert(stack, { w, x, y, z })
+ r = r + 1
+ result[r] = push
+ end,
+ [142] = function()
+ local t = remove(stack)
+ if t then
+ w, x, y, z = t[1], t[2], t[3], t[4]
+ r = r + 1
+ result[r] = pop
+ end
+ end,
+
+ [143] = function() r = r + 1 result[r] = { "right", scaled1() } p = p + 1 end,
+ [144] = function() r = r + 1 result[r] = { "right", scaled2() } p = p + 2 end,
+ [145] = function() r = r + 1 result[r] = { "right", scaled3() } p = p + 3 end,
+ [146] = function() r = r + 1 result[r] = { "right", scaled4() } p = p + 4 end,
+
+ [148] = function() w = scaled1() r = r + 1 result[r] = { "right", w } p = p + 1 end,
+ [149] = function() w = scaled2() r = r + 1 result[r] = { "right", w } p = p + 2 end,
+ [150] = function() w = scaled3() r = r + 1 result[r] = { "right", w } p = p + 3 end,
+ [151] = function() w = scaled4() r = r + 1 result[r] = { "right", w } p = p + 4 end,
+
+ [153] = function() x = scaled1() r = r + 1 result[r] = { "right", x } p = p + 1 end,
+ [154] = function() x = scaled2() r = r + 1 result[r] = { "right", x } p = p + 2 end,
+ [155] = function() x = scaled3() r = r + 1 result[r] = { "right", x } p = p + 3 end,
+ [156] = function() x = scaled4() r = r + 1 result[r] = { "right", x } p = p + 4 end,
+
+ [157] = function() r = r + 1 result[r] = { "down", scaled1() } p = p + 1 end,
+ [158] = function() r = r + 1 result[r] = { "down", scaled2() } p = p + 2 end,
+ [159] = function() r = r + 1 result[r] = { "down", scaled3() } p = p + 3 end,
+ [160] = function() r = r + 1 result[r] = { "down", scaled4() } p = p + 4 end,
+
+ [162] = function() y = scaled1() r = r + 1 result[r] = { "down", y } p = p + 1 end,
+ [163] = function() y = scaled2() r = r + 1 result[r] = { "down", y } p = p + 2 end,
+ [164] = function() y = scaled3() r = r + 1 result[r] = { "down", y } p = p + 3 end,
+ [165] = function() y = scaled3() r = r + 1 result[r] = { "down", y } p = p + 4 end,
+
+ [167] = function() z = scaled1() r = r + 1 ; result[r] = { "down", z } p = p + 4 end,
+ [168] = function() z = scaled2() r = r + 1 ; result[r] = { "down", z } p = p + 4 end,
+ [169] = function() z = scaled3() r = r + 1 ; result[r] = { "down", z } p = p + 4 end,
+ [170] = function() z = scaled4() r = r + 1 ; result[r] = { "down", z } p = p + 4 end,
+
+ [147] = function() r = r + 1 result[r] = { "right", w } end,
+ [152] = function() r = r + 1 result[r] = { "right", x } end,
+ [161] = function() r = r + 1 result[r] = { "down", y } end,
+ [166] = function() r = r + 1 result[r] = { "down", z } end,
+
+ [235] = function() f = readcardinal1(s) p = p + 1 end,
+ [236] = function() f = readcardinal2(s) p = p + 3 end,
+ [237] = function() f = readcardinal3(s) p = p + 3 end,
+ [238] = function() f = readcardinal4(s) p = p + 4 end,
+
+ [239] = function() local n = readcardinal1(s) r = r + 1 result[r] = { "special", readstring(s,n) } p = p + 1 + n end,
+ [240] = function() local n = readcardinal2(s) r = r + 1 result[r] = { "special", readstring(s,n) } p = p + 2 + n end,
+ [241] = function() local n = readcardinal3(s) r = r + 1 result[r] = { "special", readstring(s,n) } p = p + 3 + n end,
+ [242] = function() local n = readcardinal4(s) r = r + 1 result[r] = { "special", readstring(s,n) } p = p + 4 + n end,
+
+ [250] = function() local n = readcardinal1(s) r = r + 1 result[r] = { "pdf", readstring(s,n) } p = p + 1 + n end,
+ [251] = function() local n = readcardinal2(s) r = r + 1 result[r] = { "pdf", readstring(s,n) } p = p + 2 + n end,
+ [252] = function() local n = readcardinal3(s) r = r + 1 result[r] = { "pdf", readstring(s,n) } p = p + 3 + n end,
+ [253] = function() local n = readcardinal4(s) r = r + 1 result[r] = { "pdf", readstring(s,n) } p = p + 4 + n end,
+
+ }
+
+ table.setmetatableindex(actions,function(t,cmd)
+ local v
+ if cmd >= 0 and cmd <= 127 then
+ v = function()
+ if f == 0 then
+ f = 1
+ end
+ r = r + 1 ; result[r] = { "slot", f, cmd }
+ end
+ elseif cmd >= 171 and cmd <= 234 then
+ cmd = cmd - 170
+ v = function()
+ r = r + 1 ; result[r] = { "font", cmd }
+ end
+ else
+ v = dummy
+ end
+ t[cmd] = v
+ return v
+ end)
+
+ function readers.loadvf(filename,data)
+ --
+ local function someerror(m)
+ if not data then
+ data = { }
+ end
+ data.error = m or "fatal error"
+ return data
+ end
+ --
+ s = openstream(filename)
+ if not s then
+ return someerror()
+ end
+ --
+ local cmd = readcardinal1(s)
+ if cmd ~= 247 then
+ return someerror("bad preamble")
+ end
+ cmd = readcardinal1(s)
+ if cmd ~= 202 then
+ return someerror("bad version")
+ end
+ local header = readstring(s,readcardinal1(s))
+ local checksum = readcardinal4(s)
+ local designsize = idiv(readcardinal4(s),16)
+ local fonts = data and data.fonts or { }
+ local glyphs = data and data.glyphs or { }
+ --
+ alpha = 16
+ z = designsize
+ while z >= 040000000 do
+ z = rshift(z,1)
+ alpha = alpha + alpha
+ end
+ beta = idiv(256,alpha)
+ alpha = alpha * z
+ --
+ cmd = readcardinal1(s)
+ while true do
+ local n
+ if cmd == 243 then
+ n = readcardinal1(s) + 1
+ elseif cmd == 244 then
+ n = readcardinal2(s) + 1
+ elseif cmd == 245 then
+ n = readcardinal3(s) + 1
+ elseif cmd == 246 then
+ n = readcardinal4(s) + 1
+ else
+ break
+ end
+ local checksum = skipbytes(s,4)
+ local size = scaled4()
+ local designsize = idiv(readcardinal4(s),16)
+ local pathlen = readcardinal1(s)
+ local namelen = readcardinal1(s)
+ local path = readstring(s,pathlen)
+ local name = readstring(s,namelen)
+ fonts[n] = { path = path, name = name, size = size }
+ cmd = readcardinal1(s)
+ end
+ local index = 0
+ while cmd and cmd <= 242 do
+ local width = 0
+ local length = 0
+ local checksum = 0
+ if cmd == 242 then
+ length = readcardinal4(s)
+ checksum = readcardinal4(s)
+ width = readcardinal4(s)
+ else
+ length = cmd
+ checksum = readcardinal1(s)
+ width = readcardinal3(s)
+ end
+ w, x, y, z, f = 0, 0, 0, 0, false
+ stack, result, r, p = { }, { }, 0, 0
+ while p < length do
+ local cmd = readcardinal1(s)
+ p = p + 1
+ actions[cmd]()
+ end
+ local glyph = glyphs[index]
+ if glyph then
+ glyph.width = width
+ glyph.commands = result
+ else
+ glyphs[index] = {
+ width = width,
+ commands = result,
+ }
+ end
+ index = index + 1
+ if #stack > 0 then
+ -- error: more pushes than pops
+ end
+ if packet_length ~= 0 then
+ -- error: invalid packet length
+ end
+ cmd = readcardinal1(s)
+ end
+ if readcardinal1(s) ~= 248 then
+ -- error: no post
+ end
+ s, result, r = nil, nil, nil
+ if data then
+ data.glyphs = data.glyphs or glyphs
+ data.fonts = data.fonts or fonts
+ return data
+ else
+ return {
+ name = file.nameonly(filename),
+ fontarea = file.pathpart(filename),
+ glyphs = glyphs,
+ designsize = designsize,
+ header = header,
+ fonts = fonts,
+ }
+ end
+ end
+
+ -- the replacement loader (not sparse):
+
+ function readers.loadtfmvf(tfmname,size)
+ local vfname = file.addsuffix(file.nameonly(tfmfile),"vf")
+ local tfmfile = tfmname
+ local vffile = resolvers.findbinfile(vfname,"ovf")
+ if tfmfile and tfmfile ~= "" then
+ if size < 0 then
+ size = idiv(65536 * -size,100)
+ end
+ local data = readers.loadtfm(tfmfile)
+ if data.error then
+ return data
+ end
+ if vffile and vffile ~= "" then
+ data = readers.loadvf(vffile,data)
+ if data.error then
+ return data
+ end
+ end
+ local designsize = data.designsize
+ local glyphs = data.glyphs
+ local parameters = data.parameters
+ local fonts = data.fonts
+ if size ~= designsize then
+ local factor = size / designsize
+ for index, glyph in next, glyphs do
+ if next(glyph) then
+ glyph.width = round(factor*glyph.width)
+ glyph.height = round(factor*glyph.height)
+ glyph.depth = round(factor*glyph.depth)
+ local italic = glyph.italic
+ if italic == 0 then
+ glyph.italic = nil
+ else
+ glyph.italic = round(factor*glyph.italic)
+ end
+ --
+ local kerns = glyph.kerns
+ if kerns then
+ for index, kern in next, kerns do
+ kerns[index] = round(factor*kern)
+ end
+ end
+ --
+ local commands = glyph.commands
+ if commands then
+ for i=1,#commands do
+ local c = commands[i]
+ local t = c[1]
+ if t == "down" or t == "right" then
+ c[2] = round(factor*c[2])
+ elseif t == "rule" then
+ c[2] = round(factor*c[2])
+ c[3] = round(factor*c[3])
+ end
+ end
+ end
+ else
+ glyphs[index] = nil
+ end
+ end
+ for i=2,30 do
+ local p = parameters[i]
+ if p then
+ parameters[i] = round(factor*p)
+ else
+ break
+ end
+ end
+ if fonts then
+ for k, v in next, fonts do
+ v.size = round(factor*v.size)
+ end
+ end
+ else
+ for index, glyph in next, glyphs do
+ if next(glyph) then
+ if glyph.italic == 0 then
+ glyph.italic = nil
+ end
+ else
+ glyphs[index] = nil
+ end
+ end
+ end
+ --
+ parameters.slant = parameters[1]
+ parameters.space = parameters[2]
+ parameters.space_stretch = parameters[3]
+ parameters.space_shrink = parameters[4]
+ parameters.x_height = parameters[5]
+ parameters.quad = parameters[6]
+ parameters.extra_space = parameters[7]
+ --
+ for i=1,7 do
+ parameters[i] = nil -- so no danger for async
+ end
+ --
+ data.characters = glyphs
+ data.glyphs = nil
+ data.size = size
+ --
+ return data
+ end
+ end
+
+end
+
+-- inspect(readers.loadtfmvf(resolvers.find_file("mi-iwonari.tfm")))
+-- inspect(readers.loadtfm(resolvers.find_file("texnansi-palatinonova-regular.tfm")))
+-- inspect(readers.loadtfm(resolvers.find_file("cmex10.tfm")))
+-- inspect(readers.loadtfm(resolvers.find_file("cmr10.tfm")))
+-- local t = readers.loadtfmvf("texnansi-lte50019.tfm")
+-- inspect(t)
diff --git a/tex/context/base/mkiv/font-ttf.lua b/tex/context/base/mkiv/font-ttf.lua
index 58e999e26..d2fe0917c 100644
--- a/tex/context/base/mkiv/font-ttf.lua
+++ b/tex/context/base/mkiv/font-ttf.lua
@@ -319,7 +319,8 @@ local function contours2outlines_normal(glyphs,shapes) -- maybe accept the bbox
local nofsegments = 0
glyph.segments = segments
if nofcontours > 0 then
- local px, py = 0, 0 -- we could use these in calculations which saves a copy
+ local px = 0
+ local py = 0
local first = 1
for i=1,nofcontours do
local last = contours[i]
@@ -347,15 +348,20 @@ local function contours2outlines_normal(glyphs,shapes) -- maybe accept the bbox
end
control_pt = first_pt
end
- local x, y = first_pt[1], first_pt[2]
+ local x = first_pt[1]
+ local y = first_pt[2]
if not done then
- xmin, ymin, xmax, ymax = x, y, x, y
+ xmin = x
+ ymin = y
+ xmax = x
+ ymax = y
done = true
end
nofsegments = nofsegments + 1
segments[nofsegments] = { x, y, "m" } -- "moveto"
if not quadratic then
- px, py = x, y
+ px = x
+ py = y
end
local previous_pt = first_pt
for i=first,last do
@@ -375,8 +381,10 @@ local function contours2outlines_normal(glyphs,shapes) -- maybe accept the bbox
control_pt = current_pt
end
elseif current_on then
- local x1, y1 = control_pt[1], control_pt[2]
- local x2, y2 = current_pt[1], current_pt[2]
+ local x1 = control_pt[1]
+ local y1 = control_pt[2]
+ local x2 = current_pt[1]
+ local y2 = current_pt[2]
nofsegments = nofsegments + 1
if quadratic then
segments[nofsegments] = { x1, y1, x2, y2, "q" } -- "quadraticto"
@@ -386,8 +394,10 @@ local function contours2outlines_normal(glyphs,shapes) -- maybe accept the bbox
end
control_pt = false
else
- local x2, y2 = (previous_pt[1]+current_pt[1])/2, (previous_pt[2]+current_pt[2])/2
- local x1, y1 = control_pt[1], control_pt[2]
+ local x2 = (previous_pt[1]+current_pt[1])/2
+ local y2 = (previous_pt[2]+current_pt[2])/2
+ local x1 = control_pt[1]
+ local y1 = control_pt[2]
nofsegments = nofsegments + 1
if quadratic then
segments[nofsegments] = { x1, y1, x2, y2, "q" } -- "quadraticto"
@@ -403,14 +413,17 @@ local function contours2outlines_normal(glyphs,shapes) -- maybe accept the bbox
-- we're already done, probably a simple curve
else
nofsegments = nofsegments + 1
- local x2, y2 = first_pt[1], first_pt[2]
+ local x2 = first_pt[1]
+ local y2 = first_pt[2]
if not control_pt then
segments[nofsegments] = { x2, y2, "l" } -- "lineto"
elseif quadratic then
- local x1, y1 = control_pt[1], control_pt[2]
+ local x1 = control_pt[1]
+ local y1 = control_pt[2]
segments[nofsegments] = { x1, y1, x2, y2, "q" } -- "quadraticto"
else
- local x1, y1 = control_pt[1], control_pt[2]
+ local x1 = control_pt[1]
+ local y1 = control_pt[2]
x1, y1, x2, y2, px, py = curveto(x1, y1, px, py, x2, y2)
segments[nofsegments] = { x1, y1, x2, y2, px, py, "c" } -- "curveto"
-- px, py = x2, y2
@@ -474,7 +487,8 @@ local function contours2outlines_shaped(glyphs,shapes,keepcurve)
end
control_pt = first_pt
end
- local x, y = first_pt[1], first_pt[2]
+ local x = first_pt[1]
+ local y = first_pt[2]
if not done then
xmin, ymin, xmax, ymax = x, y, x, y
done = true
@@ -487,7 +501,8 @@ local function contours2outlines_shaped(glyphs,shapes,keepcurve)
segments[nofsegments] = { x, y, "m" } -- "moveto"
end
if not quadratic then
- px, py = x, y
+ px = x
+ py = y
end
local previous_pt = first_pt
for i=first,last do
@@ -497,7 +512,8 @@ local function contours2outlines_shaped(glyphs,shapes,keepcurve)
if previous_on then
if current_on then
-- both normal points
- local x, y = current_pt[1], current_pt[2]
+ local x = current_pt[1]
+ local y = current_pt[2]
if x < xmin then xmin = x elseif x > xmax then xmax = x end
if y < ymin then ymin = y elseif y > ymax then ymax = y end
if keepcurve then
@@ -505,14 +521,17 @@ local function contours2outlines_shaped(glyphs,shapes,keepcurve)
segments[nofsegments] = { x, y, "l" } -- "lineto"
end
if not quadratic then
- px, py = x, y
+ px = x
+ py = y
end
else
control_pt = current_pt
end
elseif current_on then
- local x1, y1 = control_pt[1], control_pt[2]
- local x2, y2 = current_pt[1], current_pt[2]
+ local x1 = control_pt[1]
+ local y1 = control_pt[2]
+ local x2 = current_pt[1]
+ local y2 = current_pt[2]
if quadratic then
if x1 < xmin then xmin = x1 elseif x1 > xmax then xmax = x1 end
if y1 < ymin then ymin = y1 elseif y1 > ymax then ymax = y1 end
@@ -535,8 +554,10 @@ local function contours2outlines_shaped(glyphs,shapes,keepcurve)
end
control_pt = false
else
- local x2, y2 = (previous_pt[1]+current_pt[1])/2, (previous_pt[2]+current_pt[2])/2
- local x1, y1 = control_pt[1], control_pt[2]
+ local x2 = (previous_pt[1]+current_pt[1])/2
+ local y2 = (previous_pt[2]+current_pt[2])/2
+ local x1 = control_pt[1]
+ local y1 = control_pt[2]
if quadratic then
if x1 < xmin then xmin = x1 elseif x1 > xmax then xmax = x1 end
if y1 < ymin then ymin = y1 elseif y1 > ymax then ymax = y1 end
@@ -569,8 +590,10 @@ local function contours2outlines_shaped(glyphs,shapes,keepcurve)
segments[nofsegments] = { first_pt[1], first_pt[2], "l" } -- "lineto"
end
else
- local x1, y1 = control_pt[1], control_pt[2]
- local x2, y2 = first_pt[1], first_pt[2]
+ local x1 = control_pt[1]
+ local y1 = control_pt[2]
+ local x2 = first_pt[1]
+ local y2 = first_pt[2]
if x1 < xmin then xmin = x1 elseif x1 > xmax then xmax = x1 end
if y1 < ymin then ymin = y1 elseif y1 > ymax then ymax = y1 end
if quadratic then
diff --git a/tex/context/base/mkiv/font-vir.lua b/tex/context/base/mkiv/font-vir.lua
index d65136245..c3071cac0 100644
--- a/tex/context/base/mkiv/font-vir.lua
+++ b/tex/context/base/mkiv/font-vir.lua
@@ -106,8 +106,10 @@ local function combine_assign(g, name, from, to, start, force)
if not from then from, to = 0, 0xFF00 end
if not to then to = from end
if not start then start = from end
- local fc, gc = f.characters, g.characters
- local fd, gd = f.descriptions, g.descriptions
+ local fc = f.characters
+ local gc = g.characters
+ local fd = f.descriptions
+ local gd = g.descriptions
local hn = #g.fonts+1
g.fonts[hn] = { id = id } -- no need to be sparse
for i=from,to do
@@ -133,8 +135,10 @@ end
local function combine_names(g,name,force)
local f, id = constructors.readanddefine(name,g.specification.size)
if f and id then
- local fc, gc = f.characters, g.characters
- local fd, gd = f.descriptions, g.descriptions
+ local fc = f.characters
+ local gc = g.characters
+ local fd = f.descriptions
+ local gd = g.descriptions
g.fonts[#g.fonts+1] = { id = id } -- no need to be sparse
local hn = #g.fonts
for k, v in next, fc do
@@ -149,7 +153,8 @@ local function combine_names(g,name,force)
end
local combine_feature = function(g,v)
- local key, value = v[2], v[3]
+ local key = v[2]
+ local value = v[3]
if key then
if value == nil then
value = true
diff --git a/tex/context/base/mkiv/grph-bmp.lua b/tex/context/base/mkiv/grph-bmp.lua
new file mode 100644
index 000000000..256b64309
--- /dev/null
+++ b/tex/context/base/mkiv/grph-bmp.lua
@@ -0,0 +1,85 @@
+if not modules then modules = { } end modules ['grph-bmp'] = {
+ version = 1.001,
+ comment = "companion to grph-inc.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local random = math.random
+local context = context
+
+local report_bitmap = logs.reporter("graphics","bitmap")
+
+local bitmaps = { }
+graphics.bitmaps = bitmaps
+
+local wrapimage = images.wrap
+
+function bitmaps.new(xsize,ysize,colorspace,colordepth,mask)
+ if not xsize or not ysize or xsize == 0 or ysize == 0 then
+ report_bitmap("provide 'xsize' and 'ysize' larger than zero")
+ return
+ end
+ if not colorspace then
+ report_bitmap("provide 'colorspace' (1, 2, 3, 'gray', 'rgb', 'cmyk'")
+ return
+ end
+ if not colordepth then
+ report_bitmap("provide 'colordepth' (1, 2)")
+ return
+ end
+ return graphics.identifiers.bitmap {
+ colorspace = colorspace,
+ colordepth = colordepth,
+ xsize = xsize,
+ ysize = ysize,
+ mask = mask and true or nil,
+ }
+end
+
+local function flush(bitmap)
+ return wrapimage(lpdf.injectors.bitmap(bitmap))
+end
+
+bitmaps.flush = flush
+
+function bitmaps.tocontext(bitmap,width,height)
+ if type(width) == "number" then
+ width = width .. "sp"
+ end
+ if type(height) == "number" then
+ height = height .. "sp"
+ end
+ if width or height then
+ context.scale (
+ {
+ width = width,
+ height = height,
+ },
+ flush(bitmap)
+ )
+ else
+ context(flush(bitmap))
+ end
+end
+
+local function placeholder(nx,ny)
+
+ local nx = nx or 8
+ local ny = ny or nx
+ local bitmap = bitmaps.new(nx,ny,"gray",1)
+ local data = bitmap.data
+
+ for i=1,ny do
+ local d = data[i]
+ for j=1,nx do
+ d[j] = random(100,199)
+ end
+ end
+
+ return lpdf.injectors.bitmap(bitmap)
+
+end
+
+bitmaps.placeholder = placeholder
diff --git a/tex/context/base/mkiv/grph-chk.lua b/tex/context/base/mkiv/grph-chk.lua
new file mode 100644
index 000000000..6356755aa
--- /dev/null
+++ b/tex/context/base/mkiv/grph-chk.lua
@@ -0,0 +1,276 @@
+if not modules then modules = { } end modules ['grph-inc'] = {
+ version = 1.001,
+ comment = "companion to grph-inc.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local xpcall, pcall = xpcall, pcall
+
+local bpfactor = number.dimenfactors.bp
+
+local report = logs.reporter("graphics")
+local report_inclusion = logs.reporter("graphics","inclusion")
+local report_bitmap = logs.reporter("graphics","bitmap")
+
+local checkers = figures.checkers
+
+local placeholder = graphics.bitmaps.placeholder
+
+-- This is an experiment. The following method uses Lua to handle the embedding
+-- using the epdf library. This feature will be used when we make the transition
+-- from the pre 1.10 epdf library (using an unsuported low level poppler api) to a
+-- new (lightweight, small and statically compiled) library. More on that later.
+--
+-- The method implemented below has the same performance as the hard coded inclusion
+-- but opens up some possibilities (like merging fonts) that I will look into some
+-- day.
+
+local function pdf_checker(data)
+ local request = data.request
+ local used = data.used
+ if request and used and not request.scanimage then
+ local image = lpdf.epdf.image
+ local openpdf = image.open
+ local closepdf = image.close
+ local querypdf = image.query
+ local copypage = image.copy
+ local pdfdoc = nil
+ request.scanimage = function(t)
+ pdfdoc = openpdf(t.filename,request.userpassword,request.ownerpassword)
+ if pdfdoc then
+ --
+ pdfdoc.nofcopiedpages = 0
+ --
+ local info = querypdf(pdfdoc,request.page,request.size)
+ if info then
+ local bbox = info and info.boundingbox or { 0, 0, 0, 0 }
+ local height = bbox[4] - bbox[2]
+ local width = bbox[3] - bbox[1]
+ local rotation = info.rotation or 0
+ if rotation == 90 then
+ rotation, height, width = 3, width, height
+ elseif rotation == 180 then
+ rotation = 2
+ elseif rotation == 270 then
+ rotation, height, width = 1, width, height
+ elseif rotation == 1 or rotation == 3 then
+ height, width = width, height
+ else
+ rotation = 0
+ end
+ return {
+ filename = filename,
+ -- page = 1,
+ pages = pdfdoc.nofpages,
+ width = width,
+ height = height,
+ depth = 0,
+ colordepth = 0,
+ xres = 0,
+ yres = 0,
+ xsize = width,
+ ysize = height,
+ rotation = rotation,
+ pdfdoc = pdfdoc,
+ }
+ end
+ end
+ end
+ request.copyimage = function(t)
+ if not pdfdoc then
+ pdfdoc = t.pdfdoc
+ end
+ if pdfdoc then
+ local result = copypage(pdfdoc,request.page,nil,request.compact,request.width,request.height,request.attr)
+ pdfdoc.nofcopiedpages = pdfdoc.nofcopiedpages + 1
+ if pdfdoc.nofcopiedpages >= pdfdoc.nofpages then
+ closepdf(pdfdoc)
+ pdfdoc = nil
+ t.pdfdoc = nil
+ end
+ return result
+ else
+ -- message, should not happen as we always first scan so that reopens
+ end
+ end
+ end
+ return checkers.generic(data)
+end
+
+local function wrappedidentify(identify,filename)
+ local wrapup = function() report_inclusion("fatal error reading %a",filename) end
+ local _, result = xpcall(identify,wrapup,filename)
+ if result then
+ local xsize = result.xsize or 0
+ local ysize = result.ysize or 0
+ local xres = result.xres or 0
+ local yres = result.yres or 0
+ if xres == 0 or yres == 0 then
+ xres = 300
+ yres = 300
+ end
+ result.xsize = xsize
+ result.ysize = ysize
+ result.xres = xres
+ result.yres = yres
+ result.width = result.width or ((72/xres) * xsize / bpfactor)
+ result.height = result.height or ((72/yres) * ysize / bpfactor)
+ result.depth = result.depth or 0
+ result.filename = filename
+ result.colordepth = result.colordepth or 0
+ result.colorspace = result.colorspace or 0
+ result.rotation = result.rotation or 0
+ result.orientation = result.orientation or 0
+ result.transform = result.transform or 0
+ return result
+ else
+ return { error = "fatal error" }
+ end
+end
+
+local function jpg_checker(data)
+ local request = data.request
+ local used = data.used
+ if request and used and not request.scanimage then
+ local identify = graphics.identify
+ local inject = lpdf.injectors.jpg
+ local found = false
+ request.scanimage = function(t)
+ local result = wrappedidentify(identify,t.filename)
+ found = not result.error
+ return {
+ filename = result.filename,
+ width = result.width,
+ height = result.height,
+ depth = result.depth,
+ colordepth = result.colordepth,
+ xres = result.xres,
+ yres = result.yres,
+ xsize = result.xsize,
+ ysize = result.ysize,
+ colorspace = result.colorspace,
+ rotation = result.rotation,
+ orientation = result.orientation,
+ transform = result.transform,
+ }
+ end
+ request.copyimage = function(t)
+ if found then
+ found = false
+ return inject(t)
+ end
+ end
+ end
+ return checkers.generic(data)
+end
+
+local function jp2_checker(data) -- idem as jpg
+ local request = data.request
+ local used = data.used
+ if request and used and not request.scanimage then
+ local identify = graphics.identify
+ local inject = lpdf.injectors.jp2
+ local found = false
+ request.scanimage = function(t)
+ local result = wrappedidentify(identify,t.filename)
+ found = not result.error
+ return {
+ filename = result.filename,
+ width = result.width,
+ height = result.height,
+ depth = result.depth,
+ colordepth = result.colordepth,
+ xres = result.xres,
+ yres = result.yres,
+ xsize = result.xsize,
+ ysize = result.ysize,
+ rotation = result.rotation,
+ colorspace = result.colorspace,
+ orientation = result.orientation,
+ transform = result.transform,
+ }
+ end
+ request.copyimage = function(t)
+ if found then
+ found = false
+ return inject(t)
+ end
+ end
+ end
+ return checkers.generic(data)
+end
+
+local function png_checker(data) -- same as jpg (for now)
+ local request = data.request
+ local used = data.used
+ if request and used and not request.scanimage then
+ local identify = graphics.identify
+ local inject = lpdf.injectors.png
+ local found = false
+ request.scanimage = function(t)
+ local result = wrappedidentify(identify,t.filename)
+ found = not result.error
+ return {
+ filename = result.filename,
+ width = result.width,
+ height = result.height,
+ depth = result.depth,
+ colordepth = result.colordepth,
+ xres = result.xres,
+ yres = result.yres,
+ xsize = result.xsize,
+ ysize = result.ysize,
+ rotation = result.rotation,
+ colorspace = result.colorspace,
+ tables = result.tables,
+ interlace = result.interlace,
+ filter = result.filter,
+ orientation = result.orientation,
+ transform = result.transform,
+ }
+ end
+ request.copyimage = function(t)
+ t.colorref = used.colorref -- this is a bit of a hack
+ if found then
+ found = false
+ local ok, result = pcall(inject,t)
+ if ok then
+ return result
+ else
+ report_inclusion("bad bitmap image")
+ return placeholder()
+ end
+ end
+ end
+ end
+ return checkers.generic(data)
+end
+
+
+if CONTEXTLMTXMODE then
+
+ checkers.pdf = pdf_checker
+ checkers.jpg = jpg_checker
+ checkers.jp2 = jp2_checker
+ checkers.png = png_checker
+
+else
+
+ -- yes or no ...
+
+ directives.register("graphics.pdf.uselua",function(v)
+ checkers.pdf = v and pdf_checker or nil
+ report("%s Lua based PDF inclusion",v and "enabling" or "disabling")
+ end)
+
+ -- directives.register("graphics.uselua",function(v)
+ -- checkers.pdf = v and pdf_checker or nil
+ -- checkers.jpg = v and jpg_checker or nil
+ -- checkers.jp2 = v and jp2_checker or nil
+ -- checkers.png = v and png_checker or nil
+ -- -- report("%s Lua based PDF, PNG, JPG and JP2 inclusion",v and "enabling" or "disabling")
+ -- end)
+
+end
diff --git a/tex/context/base/mkiv/grph-img.lua b/tex/context/base/mkiv/grph-img.lua
new file mode 100644
index 000000000..9acd1a5de
--- /dev/null
+++ b/tex/context/base/mkiv/grph-img.lua
@@ -0,0 +1,748 @@
+ if not modules then modules = { } end modules ['grph-img'] = {
+ version = 1.001,
+ comment = "companion to grph-inc.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- The jpg identification and inclusion code is based on the code in \LUATEX\ but as we
+-- use \LUA\ we can do it a bit cleaner. We can also use some helpers for reading from
+-- file. We could make it even more lean and mean. When all works out ok I will clean
+-- up this code a bit as we can divert more from luatex.
+
+local lower, strip = string.lower, string.strip
+local round = math.round
+local concat = table.concat
+local suffixonly = file.suffix
+
+local files = utilities.files
+local getsize = files.getsize
+local readbyte = files.readbyte
+local readstring = files.readstring
+local readcardinal = files.readcardinal
+local readcardinal2 = files.readcardinal2
+local readcardinal4 = files.readcardinal4
+local readcardinal2le = files.readcardinal2le
+local readcardinal4le = files.readcardinal4le
+local skipbytes = files.skip
+local setposition = files.setposition
+local getposition = files.getposition
+
+local setmetatableindex = table.setmetatableindex
+local setmetatablecall = table.setmetatablecall
+
+local lpdf = lpdf or { }
+local pdfmajorversion = lpdf.majorversion
+local pdfminorversion = lpdf.minorversion
+
+local graphics = graphics or { }
+local identifiers = { }
+graphics.identifiers = identifiers
+
+do
+
+ local colorspaces = {
+ [1] = 1, -- gray
+ [3] = 2, -- rgb
+ [4] = 3, -- cmyk
+ }
+
+ local tags = {
+ [0xC0] = { name = "SOF0", }, -- baseline DCT
+ [0xC1] = { name = "SOF1", }, -- extended sequential DCT
+ [0xC2] = { name = "SOF2", }, -- progressive DCT
+ [0xC3] = { name = "SOF3", supported = false }, -- lossless (sequential)
+
+ [0xC5] = { name = "SOF5", supported = false }, -- differential sequential DCT
+ [0xC6] = { name = "SOF6", supported = false }, -- differential progressive DCT
+ [0xC7] = { name = "SOF7", supported = false }, -- differential lossless (sequential)
+
+ [0xC8] = { name = "JPG", }, -- reserved for JPEG extensions
+ [0xC9] = { name = "SOF9", }, -- extended sequential DCT
+ [0xCA] = { name = "SOF10", supported = false }, -- progressive DCT
+ [0xCB] = { name = "SOF11", supported = false }, -- lossless (sequential)
+
+ [0xCD] = { name = "SOF13", supported = false }, -- differential sequential DCT
+ [0xCE] = { name = "SOF14", supported = false }, -- differential progressive DCT
+ [0xCF] = { name = "SOF15", supported = false }, -- differential lossless (sequential)
+
+ [0xC4] = { name = "DHT" }, -- define Huffman table(s)
+
+ [0xCC] = { name = "DAC" }, -- define arithmetic conditioning table
+
+ [0xD0] = { name = "RST0", zerolength = true }, -- restart
+ [0xD1] = { name = "RST1", zerolength = true }, -- restart
+ [0xD2] = { name = "RST2", zerolength = true }, -- restart
+ [0xD3] = { name = "RST3", zerolength = true }, -- restart
+ [0xD4] = { name = "RST4", zerolength = true }, -- restart
+ [0xD5] = { name = "RST5", zerolength = true }, -- restart
+ [0xD6] = { name = "RST6", zerolength = true }, -- restart
+ [0xD7] = { name = "RST7", zerolength = true }, -- restart
+
+ [0xD8] = { name = "SOI", zerolength = true }, -- start of image
+ [0xD9] = { name = "EOI", zerolength = true }, -- end of image
+ [0xDA] = { name = "SOS" }, -- start of scan
+ [0xDB] = { name = "DQT" }, -- define quantization tables
+ [0xDC] = { name = "DNL" }, -- define number of lines
+ [0xDD] = { name = "DRI" }, -- define restart interval
+ [0xDE] = { name = "DHP" }, -- define hierarchical progression
+ [0xDF] = { name = "EXP" }, -- expand reference image(s)
+
+ [0xE0] = { name = "APP0" }, -- application marker, used for JFIF
+ [0xE1] = { name = "APP1" }, -- application marker
+ [0xE2] = { name = "APP2" }, -- application marker
+ [0xE3] = { name = "APP3" }, -- application marker
+ [0xE4] = { name = "APP4" }, -- application marker
+ [0xE5] = { name = "APP5" }, -- application marker
+ [0xE6] = { name = "APP6" }, -- application marker
+ [0xE7] = { name = "APP7" }, -- application marker
+ [0xE8] = { name = "APP8" }, -- application marker
+ [0xE9] = { name = "APP9" }, -- application marker
+ [0xEA] = { name = "APP10" }, -- application marker
+ [0xEB] = { name = "APP11" }, -- application marker
+ [0xEC] = { name = "APP12" }, -- application marker
+ [0xED] = { name = "APP13" }, -- application marker
+ [0xEE] = { name = "APP14" }, -- application marker, used by Adobe
+ [0xEF] = { name = "APP15" }, -- application marker
+
+ [0xF0] = { name = "JPG0" }, -- reserved for JPEG extensions
+ [0xFD] = { name = "JPG13" }, -- reserved for JPEG extensions
+ [0xFE] = { name = "COM" }, -- comment
+
+ [0x01] = { name = "TEM", zerolength = true }, -- temporary use
+ }
+
+ -- More can be found in http://www.exif.org/Exif2-2.PDF but basically we have
+ -- good old tiff tags here.
+
+ local function read_APP1_Exif(f, xres, yres, orientation) -- untested
+ local position = false
+ local readcardinal2 = readcardinal2
+ local readcardinal4 = readcardinal4
+ -- endian II|MM
+ while true do
+ position = getposition(f)
+ local b = readbyte(f)
+ if b == 0 then
+ -- next one
+ elseif b == 0x4D and readbyte(f) == 0x4D then -- M
+ -- big endian
+ break
+ elseif b == 0x49 and readbyte(f) == 0x49 then -- I
+ -- little endian
+ readcardinal2 = readcardinal2le
+ readcardinal4 = readcardinal4le
+ break
+ else
+ -- warning "bad exif data"
+ return xres, yres, orientation
+ end
+ end
+ -- version
+ local version = readcardinal2(f)
+ if version ~= 42 then
+ return xres, yres, orientation
+ end
+ -- offset to records
+ local offset = readcardinal4(f)
+ if not offset then
+ return xres, yres, orientation
+ end
+ setposition(f,position + offset)
+ local entries = readcardinal2(f)
+ if not entries or entries == 0 then
+ return xres, yres, orientation
+ end
+ local x_res, y_res, x_res_ms, y_res_ms, x_temp, y_temp
+ local res_unit, res_unit_ms
+ for i=1,entries do
+ local tag = readcardinal2(f)
+ local kind = readcardinal2(f)
+ local size = readcardinal4(f)
+ local value = 0
+ local num = 0
+ local den = 0
+ if kind == 1 or kind == 7 then -- byte | undefined
+ value = readbyte(f)
+ skipbytes(f,3)
+ elseif kind == 3 or kind == 8 then -- (un)signed short
+ value = readcardinal2(f)
+ skipbytes(f,2)
+ elseif kind == 4 or kind == 9 then -- (un)signed long
+ value = readcardinal4(f)
+ elseif kind == 5 or kind == 10 then -- (s)rational
+ local offset = readcardinal4(f)
+ local saved = getposition(f)
+ setposition(f,position+offset)
+ num = readcardinal4(f)
+ den = readcardinal4(f)
+ setposition(f,saved)
+ else -- 2 -- ascii
+ skipbytes(f,4)
+ end
+ if tag == 274 then -- orientation
+ orientation = value
+ elseif tag == 282 then -- x resolution
+ if den ~= 0 then
+ x_res = num/den
+ end
+ elseif tag == 283 then -- y resolution
+ if den ~= 0 then
+ y_res = num/den
+ end
+ elseif tag == 296 then -- resolution unit
+ if value == 2 then
+ res_unit = 1
+ elseif value == 3 then
+ res_unit = 2.54
+ end
+ elseif tag == 0x5110 then -- pixel unit
+ res_unit_ms = value == 1
+ elseif tag == 0x5111 then -- x pixels per unit
+ x_res_ms = value
+ elseif tag == 0x5112 then -- y pixels per unit
+ y_res_ms = value
+ end
+ end
+ if x_res and y_res and res_unit and res_unit > 0 then
+ x_temp = round(x_res * res_unit)
+ y_temp = round(y_res * res_unit)
+ elseif x_res_ms and y_res_ms and res_unit_ms then
+ x_temp = round(x_res_ms * 0.0254) -- in meters
+ y_temp = round(y_res_ms * 0.0254) -- in meters
+ end
+ if x_temp and a_temp and x_temp > 0 and y_temp > 0 then
+ if (x_temp ~= x_res or y_temp ~= y_res) and x_res ~= 0 and y_res ~= 0 then
+ -- exif resolution differs from already found resolution
+ elseif x_temp == 1 or y_temp == 1 then
+ -- exif resolution is kind of weird
+ else
+ return x_temp, y_temp, orientation
+ end
+ end
+ return round(xres), round(yres), orientation
+ end
+
+ function identifiers.jpg(filename)
+ local specification = {
+ filename = filename,
+ filetype = "jpg",
+ }
+ if not filename or filename == "" then
+ specification.error = "invalid filename"
+ return specification -- error
+ end
+ local f = io.open(filename,"rb")
+ if not f then
+ specification.error = "unable to open file"
+ return specification -- error
+ end
+ specification.xres = 0
+ specification.yres = 0
+ specification.orientation = 1
+ specification.totalpages = 1
+ specification.pagenum = 1
+ specification.length = 0
+ local banner = readcardinal2(f)
+ if banner ~= 0xFFD8 then
+ specification.error = "no jpeg file"
+ return specification -- error
+ end
+ local xres = 0
+ local yres = 0
+ local orientation = 1
+ local okay = false
+ local filesize = getsize(f) -- seek end
+ local majorversion = pdfmajorversion and pdfmajorversion() or 2
+ local minorversion = pdfminorversion and pdfminorversion() or 2
+ while getposition(f) < filesize do
+ local b = readbyte(f)
+ if not b then
+ break
+ elseif b ~= 0xFF then
+ if not okay then
+ -- or check for size
+ specification.error = "incomplete file"
+ end
+ break
+ end
+ local category = readbyte(f)
+ local position = getposition(f)
+ local length = 0
+ local tagdata = tags[category]
+ if not tagdata then
+ specification.error = "invalid tag"
+ break
+ elseif tagdata.supported == false then
+ specification.error = "unsupported " .. tagdata.comment
+ break
+ end
+ local name = tagdata.name
+ if name == "SOF0" or name == "SOF1" or name == "SOF2" then
+ if majorversion == 1 and minorversion <= 2 then
+ specification.error = "no progressive DCT in PDF <= 1.2"
+ break
+ end
+ length = readcardinal2(f)
+ specification.colordepth = readcardinal(f)
+ specification.ysize = readcardinal2(f)
+ specification.xsize = readcardinal2(f)
+ specification.colorspace = colorspaces[readcardinal(f)]
+ if not specification.colorspace then
+ specification.error = "unsupported color space"
+ break
+ end
+ okay = true
+ elseif name == "APP0" then
+ length = readcardinal2(f)
+ if length > 6 then
+ local format = readstring(f,5)
+ if format == "JFIF\000" then
+ skipbytes(f,2)
+ units = readcardinal(f)
+ xres = readcardinal2(f)
+ yres = readcardinal2(f)
+ if units == 1 then
+ -- pixels per inch
+ if xres == 1 or yres == 1 then
+ -- warning
+ end
+ elseif units == 2 then
+ -- pixels per cm */
+ xres = xres * 2.54
+ yres = yres * 2.54
+ else
+ xres = 0
+ yres = 0
+ end
+ end
+ end
+ elseif name == "APP1" then
+ length = readcardinal2(f)
+ if length > 7 then
+ local format = readstring(f,5)
+ if format == "Exif\000" then
+ xres, yres, orientation = read_APP1_Exif(f,xres,yres,orientation)
+ end
+ end
+ elseif not tagdata.zerolength then
+ length = readcardinal2(f)
+ end
+ if length > 0 then
+ setposition(f,position+length)
+ end
+ end
+ f:close()
+ if not okay then
+ specification.error = specification.error or "invalid file"
+ elseif not specification.error then
+ if xres == 0 and yres ~= 0 then
+ xres = yres
+ end
+ if yres == 0 and xres ~= 0 then
+ yres = xres
+ end
+ end
+ specification.xres = xres
+ specification.yres = yres
+ specification.orientation = orientation
+ specification.length = filesize
+ return specification
+ end
+
+end
+
+do
+
+ local function read_boxhdr(specification,f)
+ local size = readcardinal4(f)
+ local kind = readstring(f,4)
+ if kind then
+ kind = strip(lower(kind))
+ else
+ kind = ""
+ end
+ if size == 1 then
+ size = readcardinal4(f) * 0xFFFF0000 + readcardinal4(f)
+ end
+ if size == 0 and kind ~= "jp2c" then -- move this
+ specification.error = "invalid size"
+ end
+ return kind, size
+ end
+
+ local function scan_ihdr(specification,f)
+ specification.ysize = readcardinal4(f)
+ specification.xsize = readcardinal4(f)
+ skipbytes(f,2) -- nc
+ specification.colordepth = readcardinal(f) + 1
+ skipbytes(f,3) -- c unkc ipr
+ end
+
+ local function scan_resc_resd(specification,f)
+ local vr_n = readcardinal2(f)
+ local vr_d = readcardinal2(f)
+ local hr_n = readcardinal2(f)
+ local hr_d = readcardinal2(f)
+ local vr_e = readcardinal(f)
+ local hr_e = readcardinal(f)
+ specification.xres = math.round((hr_n / hr_d) * math.exp(hr_e * math.log(10.0)) * 0.0254)
+ specification.yres = math.round((vr_n / vr_d) * math.exp(vr_e * math.log(10.0)) * 0.0254)
+ end
+
+ local function scan_res(specification,f,last)
+ local pos = getposition(f)
+ while true do
+ local kind, size = read_boxhdr(specification,f)
+ pos = pos + size
+ if kind == "resc" then
+ if specification.xres == 0 and specification.yres == 0 then
+ scan_resc_resd(specification,f)
+ if getposition(f) ~= pos then
+ specification.error = "invalid resc"
+ return
+ end
+ end
+ elseif tpos == "resd" then
+ scan_resc_resd(specification,f)
+ if getposition(f) ~= pos then
+ specification.error = "invalid resd"
+ return
+ end
+ elseif pos > last then
+ specification.error = "invalid res"
+ return
+ elseif pos == last then
+ break
+ end
+ if specification.error then
+ break
+ end
+ setposition(f,pos)
+ end
+ end
+
+ local function scan_jp2h(specification,f,last)
+ local okay = false
+ local pos = getposition(f)
+ while true do
+ local kind, size = read_boxhdr(specification,f)
+ pos = pos + size
+ if kind == "ihdr" then
+ scan_ihdr(specification,f)
+ if getposition(f) ~= pos then
+ specification.error = "invalid ihdr"
+ return false
+ end
+ okay = true
+ elseif kind == "res" then
+ scan_res(specification,f,pos)
+ elseif pos > last then
+ specification.error = "invalid jp2h"
+ return false
+ elseif pos == last then
+ break
+ end
+ if specification.error then
+ break
+ end
+ setposition(f,pos)
+ end
+ return okay
+ end
+
+ function identifiers.jp2(filename)
+ local specification = {
+ filename = filename,
+ filetype = "jp2",
+ }
+ if not filename or filename == "" then
+ specification.error = "invalid filename"
+ return specification -- error
+ end
+ local f = io.open(filename,"rb")
+ if not f then
+ specification.error = "unable to open file"
+ return specification -- error
+ end
+ specification.xres = 0
+ specification.yres = 0
+ specification.orientation = 1
+ specification.totalpages = 1
+ specification.pagenum = 1
+ specification.length = 0
+ local xres = 0
+ local yres = 0
+ local orientation = 1
+ local okay = false
+ local filesize = getsize(f) -- seek end
+ local majorversion = pdfmajorversion and pdfmajorversion() or 2
+ local minorversion = pdfminorversion and pdfminorversion() or 2
+ --
+ local pos = 0
+ -- signature
+ local kind, size = read_boxhdr(specification,f)
+ pos = pos + size
+ setposition(f,pos)
+ -- filetype
+ local kind, size = read_boxhdr(specification,f)
+ if kind ~= "ftyp" then
+ specification.error = "missing ftyp box"
+ return specification
+ end
+ pos = pos + size
+ setposition(f,pos)
+ while not okay do
+ local kind, size = read_boxhdr(specification,f)
+ pos = pos + size
+ if kind == "jp2h" then
+ okay = scan_jp2h(specification,f,pos)
+ elseif kind == "jp2c" and not okay then
+ specification.error = "no ihdr box found"
+ return specification
+ end
+ setposition(f,pos)
+ end
+ --
+ f:close()
+ if not okay then
+ specification.error = "invalid file"
+ elseif not specification.error then
+ if xres == 0 and yres ~= 0 then
+ xres = yres
+ end
+ if yres == 0 and xres ~= 0 then
+ yres = xres
+ end
+ end
+ specification.xres = xres
+ specification.yres = yres
+ specification.orientation = orientation
+ specification.length = filesize
+ return specification
+ end
+
+end
+
+do
+
+ -- 0 = gray "image b"
+ -- 2 = rgb "image c"
+ -- 3 = palette "image c" + "image i"
+ -- 4 = gray + alpha "image b"
+ -- 6 = rgb + alpha "image c"
+
+ -- for i=1,length/3 do
+ -- palette[i] = readstring(f,3)
+ -- end
+
+ local function grab(t,f,once)
+ if once then
+ for i=1,#t do
+ local l = t[i]
+ setposition(f,l.offset)
+ t[i] = readstring(f,l.length)
+ end
+ local data = concat(t)
+ -- t wiped in caller
+ return data
+ else
+ local data = { }
+ for i=1,#t do
+ local l = t[i]
+ setposition(f,l.offset)
+ data[i] = readstring(f,l.length)
+ end
+ return concat(data)
+ end
+ end
+
+ function identifiers.png(filename)
+ local specification = {
+ filename = filename,
+ filetype = "png",
+ }
+ if not filename or filename == "" then
+ specification.error = "invalid filename"
+ return specification -- error
+ end
+ local f = io.open(filename,"rb")
+ if not f then
+ specification.error = "unable to open file"
+ return specification -- error
+ end
+ specification.xres = 0
+ specification.yres = 0
+ specification.orientation = 1
+ specification.totalpages = 1
+ specification.pagenum = 1
+ specification.offset = 0
+ specification.length = 0
+ local filesize = getsize(f) -- seek end
+ local tables = { }
+ local banner = readstring(f,8)
+ if banner ~= "\137PNG\013\010\026\010" then
+ specification.error = "no png file"
+ return specification -- error
+ end
+ while true do
+ local position = getposition(f)
+ if position >= filesize then
+ break
+ end
+ local length = readcardinal4(f)
+ if not length then
+ break
+ end
+ local kind = readstring(f,4)
+ if kind then
+ kind = lower(kind)
+ else
+ break
+ end
+ if kind == "ihdr" then -- metadata
+ specification.xsize = readcardinal4(f)
+ specification.ysize = readcardinal4(f)
+ specification.colordepth = readcardinal(f)
+ specification.colorspace = readcardinal(f)
+ specification.compression = readcardinal(f)
+ specification.filter = readcardinal(f)
+ specification.interlace = readcardinal(f)
+ tables[kind] = true
+ elseif kind == "iend" then
+ tables[kind] = true
+ break
+ elseif kind == "phys" then
+ local x = readcardinal4(f)
+ local y = readcardinal4(f)
+ local u = readcardinal(f)
+ if u == 1 then -- meters
+ -- x = round(0.0254 * x)
+ -- y = round(0.0254 * y)
+ end
+ specification.xres = x
+ specification.yres = y
+ tables[kind] = true
+ elseif kind == "idat" or kind == "plte" or kind == "gama" or kind == "trns" then
+ local t = tables[kind]
+ if not t then
+ t = setmetatablecall(grab)
+ tables[kind] = t
+ end
+ t[#t+1] = {
+ offset = getposition(f),
+ length = length,
+ }
+ else
+ tables[kind] = true
+ end
+ setposition(f,position+length+12) -- #size #kind #crc
+ end
+ specification.tables = tables
+ return specification
+ end
+
+end
+
+do
+
+ local function gray(t,k)
+ local v = 0
+ t[k] = v
+ return v
+ end
+
+ local function rgb(t,k)
+ local v = { 0, 0, 0 }
+ t[k] = v
+ return v
+ end
+
+ local function cmyk(t,k)
+ local v = { 0, 0, 0, 0 }
+ t[k] = v
+ return v
+ end
+
+ function identifiers.bitmap(specification)
+ local xsize = specification.xsize or 0
+ local ysize = specification.ysize or 0
+ local width = specification.width or xsize * 65536
+ local height = specification.height or ysize * 65536
+ local colordepth = specification.colordepth or 1 -- 1 .. 2
+ local colorspace = specification.colorspace or 1 -- 1 .. 3
+ local pixel = false
+ local data = specification.data
+ local mask = specification.mask
+ if colorspace == 1 or colorspace == "gray" then
+ pixel = gray
+ colorspace = 1
+ elseif colorspace == 2 or colorspace == "rgb" then
+ pixel = rgb
+ colorspace = 2
+ elseif colorspace == 3 or colorspace == "cmyk" then
+ pixel = cmyk
+ colorspace = 3
+ else
+ return
+ end
+ if colordepth == 8 then
+ colordepth = 1
+ elseif colordepth == 16 then
+ colordepth = 2
+ end
+ if colordepth > 1 then
+ -- not yet
+ return
+ end
+ if data then
+ -- assume correct data
+ else
+ data = { }
+ for i=1,ysize do
+ data[i] = setmetatableindex(pixel)
+ end
+ end
+ if mask == true then
+ mask = { }
+ for i=1,ysize do
+ mask[i] = setmetatableindex(gray)
+ end
+ end
+ local specification = {
+ xsize = xsize,
+ ysize = ysize,
+ width = width,
+ height = height,
+ colordepth = colordepth,
+ colorspace = colorspace,
+ data = data,
+ mask = mask,
+ }
+ return specification
+ end
+
+end
+
+function graphics.identify(filename,filetype)
+ local identify = filetype and identifiers[filetype]
+ if identify then
+ return identify(filename)
+ end
+ local identify = identifiers[suffixonly(filename)]
+ if identify then
+ identify = identify(filename)
+ else
+ identify = {
+ filename = filename,
+ filetype = filetype,
+ error = "identification failed",
+ }
+ end
+ -- inspect(identify)
+ return identify
+end
+
+-- inspect(identifiers.jpg("t:/sources/hacker.jpg"))
+-- inspect(identifiers.png("t:/sources/mill.png"))
diff --git a/tex/context/base/mkiv/grph-inc.lua b/tex/context/base/mkiv/grph-inc.lua
index ee4ed2a28..0856e0de9 100644
--- a/tex/context/base/mkiv/grph-inc.lua
+++ b/tex/context/base/mkiv/grph-inc.lua
@@ -124,8 +124,8 @@ local ctx_doboxfigureobject = context.doboxfigureobject
function checkimage(figure)
if figure then
- local width = figure.width
- local height = figure.height
+ local width = figure.width or 0
+ local height = figure.height or 0
if width <= 0 or height <= 0 then
report_inclusion("image %a has bad dimensions (%p,%p), discarding",figure.filename or "?",width,height)
return false, "bad dimensions"
@@ -162,28 +162,28 @@ end
local __img__ = type(img) == "table" and img or { }
images.__img__ =__img__
-local img_new = __img__.new
-local img_scan = __img__.scan
-local img_copy = __img__.copy
-local img_wrap = __img__.node
-local img_embed = __img__.immediatewrite
+local imgnew = __img__.new
+local imgscan = __img__.scan
+local imgcopy = __img__.copy
+local imgwrap = __img__.node
+local imgembed = __img__.immediatewrite
-if img_new then
+if imgnew then
-- catch (actually we should be less picky in img)
- local __img__new__ = img_new
- img_new = function(t)
+ local __img__new__ = imgnew
+ imgnew = function(t)
t.kind = nil
return __img__new__(t)
end
end
-updaters.register("backend.update",function()
+updaters.register("backend.update.img",function()
local img = images.__img__
- img_new = img.new
- img_scan = img.scan
- img_copy = img.copy
- img_wrap = img.wrap
- img_embed = img.embed
+ imgnew = img.new
+ imgscan = img.scan
+ imgcopy = img.copy
+ imgwrap = img.wrap
+ imgembed = img.embed
end)
local imagekeys = { -- only relevant ones
@@ -217,25 +217,25 @@ images.sizes = imagesizes
-- new interface
local function createimage(specification)
- return img_new(specification)
+ return imgnew(specification)
end
local function copyimage(specification)
- return img_copy(specification)
+ return imgcopy(specification)
end
local function scanimage(specification)
- return img_scan(specification)
+ return imgscan(specification)
end
local function embedimage(specification)
-- write the image to file
- return img_embed(specification)
+ return imgembed(specification)
end
local function wrapimage(specification)
-- create an image rule
- return img_wrap(specification)
+ return imgwrap(specification)
end
images.create = createimage
@@ -918,6 +918,7 @@ local function register(askedname,specification)
format = suffix
end
end
+specification.format = format
elseif io.exists(oldname) then
report_inclusion("file %a is bugged",oldname)
if format and imagetypes[format] then
@@ -1285,6 +1286,7 @@ function figures.identify(data)
for i=1,#list do
local identifier = list[i]
local data = identifier(data)
+-- if data and (not data.status and data.status.status > 0) then
if data and (not data.status and data.status.status > 0) then
break
end
@@ -1575,6 +1577,11 @@ function figures.getrealpage(index)
return pofimages[index] or 0
end
+local function updatepage(specification)
+ local n = specification.n
+ pofimages[n] = pofimages[n] or tex.count.realpageno -- so when reused we register the first one only
+end
+
function includers.generic(data)
local dr, du, ds = data.request, data.used, data.status
-- here we set the 'natural dimensions'
@@ -1603,18 +1610,16 @@ function includers.generic(data)
nofimages = nofimages + 1
ds.pageindex = nofimages
local image = wrapimage(figure)
- local pager = new_latelua(function()
- pofimages[nofimages] = pofimages[nofimages] or tex.count.realpageno -- so when reused we register the first one only
- end)
- image.next = pager
- pager.prev = image
- local box = hpack(image)
- -- indexed[figure.index] = figure
- box.width = figure.width
- box.height = figure.height
- box.depth = 0
+ local pager = new_latelua { action = updatepage, n = nofimages }
+ image.next = pager
+ pager.prev = image
+ local box = hpack(image)
+ box.width = figure.width
+ box.height = figure.height
+ box.depth = 0
texsetbox(nr,box)
ds.objectnumber = figure.objnum
+ -- indexed[figure.index] = figure
ctx_relocateexternalfigure()
end
return data
@@ -1691,6 +1696,7 @@ local ctx_docheckfiguremps = context.docheckfiguremps
local function internal(askedname)
local spec, mprun, mpnum = match(lower(askedname),"mprun([:%.]?)(.-)%.(%d+)")
+ -- mpnum = tonumber(mpnum) or 0 -- can be string or number, fed to context anyway
if spec ~= "" then
return mprun, mpnum
else
diff --git a/tex/context/base/mkiv/grph-inc.mkiv b/tex/context/base/mkiv/grph-inc.mkiv
index 6379c150d..20e7c11a6 100644
--- a/tex/context/base/mkiv/grph-inc.mkiv
+++ b/tex/context/base/mkiv/grph-inc.mkiv
@@ -40,7 +40,7 @@
%D Including graphics is complicated by the fact that we need to locate them first,
%D optionally manipulate them and scale then next. Lookups are to be done as efficient
%D as possible and inclusion of the data might happens only once. In \MKIV\ much of this
-%D is delegated to the \LUA\ end. There is nor so much less code as in \MKII\ but it's
+%D is delegated to the \LUA\ end. There is not so much less code as in \MKII\ but it's
%D more powerful, flexible, pluggable and some of the extended functionality has been
%D moved from modules to the core. The overall functionality is rather stable and has
%D not changed much over the years.
diff --git a/tex/context/base/mkiv/l-bit32.lua b/tex/context/base/mkiv/l-bit32.lua
index 5f35b8fee..25716e0a8 100644
--- a/tex/context/base/mkiv/l-bit32.lua
+++ b/tex/context/base/mkiv/l-bit32.lua
@@ -20,7 +20,7 @@ elseif utf8 then
-- lua 5.3: bitwise.lua, v 1.24 2014/12/26 17:20:53 roberto
- bit32 = load ( [[
+ load ( [[
local select = select -- instead of: arg = { ... }
bit32 = {
@@ -105,13 +105,13 @@ bit32 = {
return ((a & ~(mask << f)) | ((v & mask) << f)) & 0xFFFFFFFF
end,
}
- ]] )
+ ]] ) ()
elseif bit then
-- luajit (for now)
- bit32 = load ( [[
+ load ( [[
local band, bnot, rshift, lshift = bit.band, bit.bnot, bit.rshift, bit.lshift
bit32 = {
@@ -135,7 +135,7 @@ bit32 = {
rrotate = bit.ror,
rshift = rshift,
}
- ]] )
+ ]] ) ()
else
@@ -146,5 +146,3 @@ else
xpcall(function() local _, t = require("bit32") if t then bit32 = t end return end,function() end)
end
-
-return bit32 or false
diff --git a/tex/context/base/mkiv/l-dir.lua b/tex/context/base/mkiv/l-dir.lua
index b0b2c5283..325039cb1 100644
--- a/tex/context/base/mkiv/l-dir.lua
+++ b/tex/context/base/mkiv/l-dir.lua
@@ -91,13 +91,15 @@ local function glob_pattern_function(path,patt,recurse,action)
end
local dirs
local nofdirs = 0
- for name in walkdir(usedpath) do
+ for name, mode, size, time in walkdir(usedpath) do
if name ~= "." and name ~= ".." then
local full = path .. name
- local mode = attributes(full,'mode')
+ if mode == nil then
+ mode = attributes(full,'mode')
+ end
if mode == 'file' then
if not patt or find(full,patt) then
- action(full)
+ action(full,size,time)
end
elseif recurse and mode == "directory" then
if dirs then
@@ -134,10 +136,12 @@ local function glob_pattern_table(path,patt,recurse,result)
local dirs
local nofdirs = 0
local noffiles = #result
- for name, a in walkdir(usedpath) do
+ for name, mode in walkdir(usedpath) do
if name ~= "." and name ~= ".." then
local full = path .. name
- local mode = attributes(full,'mode')
+ if mode == nil then
+ mode = attributes(full,'mode')
+ end
if mode == 'file' then
if not patt or find(full,patt) then
noffiles = noffiles + 1
@@ -193,7 +197,7 @@ local function collectpattern(path,patt,recurse,result)
if not find(path,"/$") then
path = path .. '/'
end
- for name in scanner, first do
+ for name in scanner, first do -- cna be optimized
if name == "." then
-- skip
elseif name == ".." then
@@ -321,11 +325,13 @@ local function globfiles(path,recurse,func,files) -- func == pattern or function
end
files = files or { }
local noffiles = #files
- for name in walkdir(path) do
+ for name, mode in walkdir(path) do
if find(name,"^%.") then
--- skip
else
- local mode = attributes(name,'mode')
+ if mode == nil then
+ mode = attributes(name,'mode')
+ end
if mode == "directory" then
if recurse then
globfiles(path .. "/" .. name,recurse,func,files)
@@ -350,11 +356,13 @@ local function globdirs(path,recurse,func,files) -- func == pattern or function
end
files = files or { }
local noffiles = #files
- for name in walkdir(path) do
+ for name, mode in walkdir(path) do
if find(name,"^%.") then
--- skip
else
- local mode = attributes(name,'mode')
+ if mode == nil then
+ mode = attributes(name,'mode')
+ end
if mode == "directory" then
if not func or func(name) then
noffiles = noffiles + 1
@@ -597,8 +605,7 @@ local stack = { }
function dir.push(newdir)
local curdir = currentdir()
insert(stack,curdir)
- if newdir and newdir ~= "" then
- chdir(newdir)
+ if newdir and newdir ~= "" and chdir(newdir) then
return newdir
else
return curdir
diff --git a/tex/context/base/mkiv/l-file.lua b/tex/context/base/mkiv/l-file.lua
index 46b6847d3..1b039a438 100644
--- a/tex/context/base/mkiv/l-file.lua
+++ b/tex/context/base/mkiv/l-file.lua
@@ -73,13 +73,9 @@ local P, R, S, C, Cs, Cp, Cc, Ct = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cs, lpeg
-- better this way:
------ tricky = S("/\\") * P(-1)
local attributes = lfs.attributes
function lfs.isdir(name)
- -- if not lpegmatch(tricky,name) then
- -- name = name .. "/."
- -- end
return attributes(name,"mode") == "directory"
end
@@ -336,43 +332,52 @@ end
-- But after some testing Taco and I came up with the more robust
-- variant:
-function file.is_writable(name)
- if not name then
- -- error
- elseif lfs.isdir(name) then
- name = name .. "/m_t_x_t_e_s_t.tmp"
- local f = io.open(name,"wb")
- if f then
- f:close()
- os.remove(name)
- return true
- end
- elseif lfs.isfile(name) then
- local f = io.open(name,"ab")
- if f then
- f:close()
- return true
- end
- else
- local f = io.open(name,"ab")
- if f then
- f:close()
- os.remove(name)
- return true
+if lfs.isreadablefile and lfs.iswritablefile then
+
+ file.is_readable = lfs.isreadablefile
+ file.is_writable = lfs.iswritablefile
+
+else
+
+ function file.is_writable(name)
+ if not name then
+ -- error
+ elseif lfs.isdir(name) then
+ name = name .. "/m_t_x_t_e_s_t.tmp"
+ local f = io.open(name,"wb")
+ if f then
+ f:close()
+ os.remove(name)
+ return true
+ end
+ elseif lfs.isfile(name) then
+ local f = io.open(name,"ab")
+ if f then
+ f:close()
+ return true
+ end
+ else
+ local f = io.open(name,"ab")
+ if f then
+ f:close()
+ os.remove(name)
+ return true
+ end
end
+ return false
end
- return false
-end
-local readable = P("r") * Cc(true)
+ local readable = P("r") * Cc(true)
-function file.is_readable(name)
- if name then
- local a = attributes(name)
- return a and lpegmatch(readable,a.permissions) or false
- else
- return false
+ function file.is_readable(name)
+ if name then
+ local a = attributes(name)
+ return a and lpegmatch(readable,a.permissions) or false
+ else
+ return false
+ end
end
+
end
file.isreadable = file.is_readable -- depricated
diff --git a/tex/context/base/mkiv/l-lua.lua b/tex/context/base/mkiv/l-lua.lua
index ddd499022..5570e83dc 100644
--- a/tex/context/base/mkiv/l-lua.lua
+++ b/tex/context/base/mkiv/l-lua.lua
@@ -228,10 +228,10 @@ elseif not ffi.number then
ffi.number = tonumber
end
-if not bit32 then -- and utf8 then
- -- bit32 = load ( [[ -- replacement code with 5.3 syntax so that 5.2 doesn't bark on it ]] )
- bit32 = require("l-bit32")
-end
+-- if not bit32 then -- and utf8 then
+-- -- bit32 = load ( [[ -- replacement code with 5.3 syntax so that 5.2 doesn't bark on it ]] )
+-- bit32 = require("l-bit32")
+-- end
-- We need this due a bug in luatex socket loading:
@@ -248,3 +248,8 @@ end
-- if not loaded["socket.smtp"] then loaded["socket.smtp"] = socket.smtp end
-- if not loaded["socket.tp"] then loaded["socket.tp"] = socket.tp end
-- if not loaded["socket.url"] then loaded["socket.url"] = socket.url end
+
+if LUAVERSION > 5.3 then
+ -- collectgarbage("collect")
+ -- collectgarbage("generational") -- crashes on unix
+end
diff --git a/tex/context/base/mkiv/l-os.lua b/tex/context/base/mkiv/l-os.lua
index cf469f79d..aa04e254d 100644
--- a/tex/context/base/mkiv/l-os.lua
+++ b/tex/context/base/mkiv/l-os.lua
@@ -227,25 +227,12 @@ local launchers = {
}
function os.launch(str)
- execute(format(launchers[os.name] or launchers.unix,str))
+ local command = format(launchers[os.name] or launchers.unix,str)
+ -- todo: pcall
+-- print(command)
+ execute(command)
end
-if not os.times then -- ?
- -- utime = user time
- -- stime = system time
- -- cutime = children user time
- -- cstime = children system time
- function os.times()
- return {
- utime = os.gettimeofday(), -- user
- stime = 0, -- system
- cutime = 0, -- children user
- cstime = 0, -- children system
- }
- end
-end
-
-
local gettimeofday = os.gettimeofday or os.clock
os.gettimeofday = gettimeofday
diff --git a/tex/context/base/mkiv/l-table.lua b/tex/context/base/mkiv/l-table.lua
index eae135139..192347b06 100644
--- a/tex/context/base/mkiv/l-table.lua
+++ b/tex/context/base/mkiv/l-table.lua
@@ -8,7 +8,7 @@ if not modules then modules = { } end modules ['l-table'] = {
local type, next, tostring, tonumber, select = type, next, tostring, tonumber, select
local table, string = table, string
-local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
+local concat, sort = table.concat, table.sort
local format, lower, dump = string.format, string.lower, string.dump
local getmetatable, setmetatable = getmetatable, setmetatable
local lpegmatch, patterns = lpeg.match, lpeg.patterns
@@ -26,7 +26,8 @@ function table.getn(t)
end
function table.strip(tab)
- local lst, l = { }, 0
+ local lst = { }
+ local l = 0
for i=1,#tab do
local s = lpegmatch(stripper,tab[i]) or ""
if s == "" then
@@ -41,7 +42,8 @@ end
function table.keys(t)
if t then
- local keys, k = { }, 0
+ local keys = { }
+ local k = 0
for key in next, t do
k = k + 1
keys[k] = key
@@ -145,28 +147,30 @@ end
local function sortedkeys(tab)
if tab then
- local srt, category, s = { }, 0, 0 -- 0=unknown 1=string, 2=number 3=mixed
+ local srt = { }
+ local category = 0 -- 0=unknown 1=string, 2=number 3=mixed
+ local s = 0
for key in next, tab do
s = s + 1
srt[s] = key
- if category == 3 then
- -- no further check
- elseif category == 1 then
- if type(key) ~= "string" then
- category = 3
- end
- elseif category == 2 then
- if type(key) ~= "number" then
- category = 3
- end
- else
+ if category ~= 3 then
local tkey = type(key)
- if tkey == "string" then
- category = 1
- elseif tkey == "number" then
- category = 2
+ if category == 1 then
+ if tkey ~= "string" then
+ category = 3
+ end
+ elseif category == 2 then
+ if tkey ~= "number" then
+ category = 3
+ end
else
- category = 3
+ if tkey == "string" then
+ category = 1
+ elseif tkey == "number" then
+ category = 2
+ else
+ category = 3
+ end
end
end
end
@@ -185,7 +189,8 @@ end
local function sortedhashonly(tab)
if tab then
- local srt, s = { }, 0
+ local srt = { }
+ local s = 0
for key in next, tab do
if type(key) == "string" then
s = s + 1
@@ -203,7 +208,8 @@ end
local function sortedindexonly(tab)
if tab then
- local srt, s = { }, 0
+ local srt = { }
+ local s = 0
for key in next, tab do
if type(key) == "number" then
s = s + 1
@@ -221,7 +227,8 @@ end
local function sortedhashkeys(tab,cmp) -- fast one
if tab then
- local srt, s = { }, 0
+ local srt = { }
+ local s = 0
for key in next, tab do
if key then
s= s + 1
@@ -317,7 +324,9 @@ end
-- end
function table.merge(t, ...) -- first one is target
- t = t or { }
+ if not t then
+ t = { }
+ end
for i=1,select("#",...) do
for k, v in next, (select(i,...)) do
t[k] = v
@@ -383,7 +392,8 @@ end
-- end
function table.imerged(...)
- local tmp, ntmp = { }, 0
+ local tmp = { }
+ local ntmp = 0
for i=1,select("#",...) do
local nst = select(i,...)
for j=1,#nst do
@@ -420,7 +430,9 @@ end
-- todo : copy without metatable
local function copy(t,tables) -- taken from lua wiki, slightly adapted
- tables = tables or { }
+ if not tables then
+ tables = { }
+ end
local tcopy = { }
if not tables[t] then
tables[t] = tcopy
@@ -471,7 +483,8 @@ function table.tohash(t,value)
end
function table.fromhash(t)
- local hsh, h = { }, 0
+ local hsh = { }
+ local h = 0
for k, v in next, t do
if v then
h = h + 1
@@ -669,7 +682,8 @@ local function do_serialize(root,name,depth,level,indexed)
end
-- we could check for k (index) being number (cardinal)
if root and next(root) ~= nil then
- local first, last = nil, 0
+ local first = nil
+ local last = 0
if compact then
last = #root
for k=1,last do
@@ -960,7 +974,8 @@ end
-- number : [number] = { }
function table.serialize(root,name,specification)
- local t, n = { }, 0
+ local t = { }
+ local n = 0
local function flush(s)
n = n + 1
t[n] = s
@@ -984,13 +999,15 @@ function table.tofile(filename,root,name,specification)
local f = io.open(filename,'w')
if f then
if maxtab > 1 then
- local t, n = { }, 0
+ local t = { }
+ local n = 0
local function flush(s)
n = n + 1
t[n] = s
if n > maxtab then
f:write(concat(t,"\n"),"\n") -- hm, write(sometable) should be nice
- t, n = { }, 0 -- we could recycle t if needed
+ t = { } -- we could recycle t if needed
+ n = 0
end
end
serialize(flush,root,name,specification)
@@ -1008,12 +1025,12 @@ end
local function flattened(t,f,depth) -- also handles { nil, 1, nil, 2 }
if f == nil then
- f = { }
+ f = { }
depth = 0xFFFF
elseif tonumber(f) then
-- assume that only two arguments are given
depth = f
- f = { }
+ f = { }
elseif not depth then
depth = 0xFFFF
end
@@ -1101,8 +1118,12 @@ local function are_equal(a,b,n,m) -- indexed
if a == b then
return true
elseif a and b and #a == #b then
- n = n or 1
- m = m or #a
+ if not n then
+ n = 1
+ end
+ if not m then
+ m = #a
+ end
for i=n,m do
local ai, bi = a[i], b[i]
if ai==bi then
@@ -1215,7 +1236,8 @@ end
function table.reversed(t)
if t then
- local tt, tn = { }, #t
+ local tt = { }
+ local tn = #t
if tn > 0 then
local ttn = 0
for i=tn,1,-1 do
@@ -1332,8 +1354,8 @@ end
function table.unique(old)
local hash = { }
- local new = { }
- local n = 0
+ local new = { }
+ local n = 0
for i=1,#old do
local oi = old[i]
if not hash[oi] then
@@ -1354,12 +1376,14 @@ end
function table.values(t,s) -- optional sort flag
if t then
- local values, keys, v = { }, { }, 0
+ local values = { }
+ local keys = { }
+ local v = 0
for key, value in next, t do
if not keys[value] then
v = v + 1
values[v] = value
- keys[k] = key
+ keys[k] = key
end
end
if s then
diff --git a/tex/context/base/mkiv/lang-dis.lua b/tex/context/base/mkiv/lang-dis.lua
index 5603d1193..90e84f65d 100644
--- a/tex/context/base/mkiv/lang-dis.lua
+++ b/tex/context/base/mkiv/lang-dis.lua
@@ -180,7 +180,6 @@ end
-- experiment: for now not in not in export mode!
local flatten = languages.flatten
-local getlist = nodes.getlist
nodes.handlers.flattenline = flatten
diff --git a/tex/context/base/mkiv/lang-txt.lua b/tex/context/base/mkiv/lang-txt.lua
index d287f7e6d..daf8f787e 100644
--- a/tex/context/base/mkiv/lang-txt.lua
+++ b/tex/context/base/mkiv/lang-txt.lua
@@ -64,6 +64,8 @@ local languages = languages
languages.data = languages.data or utilities.storage.allocate { }
local data = languages.data
+local hairspace = utf.char(0x200A)
+
data.labels={
["btx"]={
["In"]={
@@ -627,6 +629,18 @@ data.labels={
},
},
["texts"]={
+ ["following:singular"]={
+ ["labels"]={
+ ["en"]="f.",
+ ["fr"]=hairspace .. "sq",
+ },
+ },
+ ["following:plural"]={
+ ["labels"]={
+ ["en"]="ff.",
+ ["fr"]=hairspace .. "sqq",
+ },
+ },
["and"]={
["labels"]={
["af"]="",
diff --git a/tex/context/base/mkiv/lpdf-ano.lua b/tex/context/base/mkiv/lpdf-ano.lua
index bf9d6926f..49bf973c9 100644
--- a/tex/context/base/mkiv/lpdf-ano.lua
+++ b/tex/context/base/mkiv/lpdf-ano.lua
@@ -157,7 +157,9 @@ directives.register("references.border",function(v)
local c = m and m[v]
local v = c and attributes.colors.value(c)
if v then
- local r, g, b = v[3], v[4], v[5]
+ local r = v[3]
+ local g = v[4]
+ local b = v[5]
-- if r == g and g == b then
-- pdf_border_color = pdfarray { r } -- reduced, not not ... bugged viewers
-- else
@@ -466,13 +468,15 @@ local pagedestinations = setmetatableindex(function(t,k) -- not the same as the
return v
end)
-local function flushdestination(width,height,depth,names,view)
- local r = pdfpagereference(texgetcount("realpageno"))
+local function flushdestination(specification)
+ local names = specification.names
+ local view = specification.view
+ local r = pdfpagereference(texgetcount("realpageno"))
if (references.innermethod ~= v_name) and (view == defaultview or not view or view == "") then
r = pagedestinations[r]
else
local action = view and destinationactions[view] or defaultaction
- r = pdfdelayedobject(action(r,width,height,depth,offset))
+ r = pdfdelayedobject(action(r,specification.width,specification.height,specification.depth,offset))
end
for n=1,#names do
local name = names[n]
@@ -554,7 +558,14 @@ function nodeinjections.destination(width,height,depth,names,view)
end
end
if doview then
- return new_latelua(function() flushdestination(width,height,depth,names,view) end)
+ return new_latelua {
+ action = flushdestination,
+ width = width,
+ height = height,
+ depth = depth,
+ names = names,
+ view = view,
+ }
end
end
@@ -766,24 +777,26 @@ setmetatableindex(hashed,function(t,k)
return v
end)
-local function finishreference(width,height,depth,prerolled) -- %0.2f looks okay enough (no scaling anyway)
- local annot = hashed[f_annot(prerolled,pdfrectangle(width,height,depth))]
+local function finishreference(specification) -- %0.2f looks okay enough (no scaling anyway)
+ local annot = hashed[f_annot(specification.prerolled,pdfrectangle(specification.width,specification.height,specification.depth))]
nofused = nofused + 1
return pdfregisterannotation(annot)
end
-local function finishannotation(width,height,depth,prerolled,r)
+local function finishannotation(specification)
+ local prerolled = specification.prerolled
+ local objref = specification.objref
if type(prerolled) == "function" then
prerolled = prerolled()
end
- local annot = f_annot(prerolled,pdfrectangle(width,height,depth))
- if r then
- pdfdelayedobject(annot,r)
+ local annot = f_annot(prerolled,pdfrectangle(specification.width,specification.height,specification.depth))
+ if objref then
+ pdfdelayedobject(annot,objref)
else
- r = pdfdelayedobject(annot)
+ objref = pdfdelayedobject(annot)
end
nofspecial = nofspecial + 1
- return pdfregisterannotation(r)
+ return pdfregisterannotation(objref)
end
function nodeinjections.reference(width,height,depth,prerolled)
@@ -791,17 +804,30 @@ function nodeinjections.reference(width,height,depth,prerolled)
if trace_references then
report_references("link: width %p, height %p, depth %p, prerolled %a",width,height,depth,prerolled)
end
- return new_latelua(function() finishreference(width,height,depth,prerolled) end)
+ return new_latelua {
+ action = finishreference,
+ width = width,
+ height = height,
+ depth = depth,
+ prerolled = prerolled,
+ }
end
end
-function nodeinjections.annotation(width,height,depth,prerolled,r)
+function nodeinjections.annotation(width,height,depth,prerolled,objref)
if prerolled then
if trace_references then
report_references("special: width %p, height %p, depth %p, prerolled %a",width,height,depth,
type(prerolled) == "string" and prerolled or "-")
end
- return new_latelua(function() finishannotation(width,height,depth,prerolled,r or false) end)
+ return new_latelua {
+ action = finishannotation,
+ width = width,
+ height = height,
+ depth = depth,
+ prerolled = prerolled,
+ objref = objref or false,
+ }
end
end
@@ -1202,7 +1228,8 @@ end
local function build(levels,start,parent,method,nested)
local startlevel = levels[start].level
local noflevels = #levels
- local i, n = start, 0
+ local i = start
+ local n = 0
local child, entry, m, prev, first, last, f, l
while i and i <= noflevels do
local current = levels[i]
diff --git a/tex/context/base/mkiv/lpdf-col.lua b/tex/context/base/mkiv/lpdf-col.lua
index 1645a72ed..9ba64abba 100644
--- a/tex/context/base/mkiv/lpdf-col.lua
+++ b/tex/context/base/mkiv/lpdf-col.lua
@@ -342,7 +342,9 @@ local function registersomeindexcolor(name,noffractions,names,p,colorspace,range
colorspace,
pdfreference(n),
}
- local vector, set, n = { }, { }, #values
+ local vector = { }
+ local set = { }
+ local n = #values
for i=255,0,-1 do
for j=1,n do
set[j] = format("%02X",round(values[j]*i))
@@ -427,7 +429,8 @@ function codeinjections.setfigurecolorspace(data,figure)
local ref = indexcolorref(color)
if ref then
figure.colorspace = ref
- data.used.color = color
+ data.used.color = color
+ data.used.colorref = ref
end
end
end
@@ -519,13 +522,21 @@ local function lpdfcolor(model,ca,default) -- todo: use gray when no color
local s = cv[2]
return f_gray(s,s)
elseif model == 3 then
- local r, g, b = cv[3], cv[4], cv[5]
+ local r = cv[3]
+ local g = cv[4]
+ local b = cv[5]
return f_rgb(r,g,b,r,g,b)
elseif model == 4 then
- local c, m, y, k = cv[6],cv[7],cv[8],cv[9]
+ local c = cv[6]
+ local m = cv[7]
+ local y = cv[8]
+ local k = cv[9]
return f_cmyk(c,m,y,k,c,m,y,k)
else
- local n,f,d,p = cv[10],cv[11],cv[12],cv[13]
+ local n = cv[10]
+ local f = cv[11]
+ local d = cv[12]
+ local p = cv[13]
if type(p) == "string" then
p = gsub(p,","," ") -- brr misuse of spot
end
diff --git a/tex/context/base/mkiv/lpdf-emb.lua b/tex/context/base/mkiv/lpdf-emb.lua
new file mode 100644
index 000000000..27fb2dc9a
--- /dev/null
+++ b/tex/context/base/mkiv/lpdf-emb.lua
@@ -0,0 +1,1839 @@
+if not modules then modules = { } end modules ['lpdf-ini'] = {
+ version = 1.001,
+ comment = "companion to lpdf-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- vkgoeswild: Pink Floyd - Shine on You Crazy Diamond - piano cover
+
+-- At some point I wanted to have access to the shapes so that we could use them in
+-- metapost. So, after looking at the cff and ttf specifications, I decided to write
+-- parsers. At somepoint we needed a cff parser anyway in order to calculate the
+-- dimensions. Then variable fonts came around and a option was added to recreate
+-- streams of operators and a logical next step was to do all inclusion that way. It
+-- was only then that I found out that some of the juggling also happens in the the
+-- backend, but spread over places, so I could have saved myself some time
+-- deciphering the specifications. Anyway, here we go.
+
+local next, type, unpack = next, type, unpack
+local char, byte, gsub, sub, match, rep, gmatch = string.char, string.byte, string.gsub, string.sub, string.match, string.rep, string.gmatch
+local formatters = string.formatters
+local format = string.format
+local concat, sortedhash, sort = table.concat, table.sortedhash, table.sort
+local utfchar = utf.char
+local random, round, max, abs, ceiling = math.random, math.round, math.max, math.abs, math.ceiling
+local extract, lshift, rshift, band, bor = bit32.extract, bit32.lshift, bit32.rshift, bit32.band, bit32.bor
+local idiv = number.idiv
+local setmetatableindex = table.setmetatableindex
+
+local pdfnull = lpdf.null
+local pdfdictionary = lpdf.dictionary
+local pdfarray = lpdf.array
+local pdfconstant = lpdf.constant
+local pdfstring = lpdf.string
+local pdfreference = lpdf.reference
+local pdfreserveobject = lpdf.reserveobject
+local pdfflushobject = lpdf.flushobject
+local pdfflushstreamobject = lpdf.flushstreamobject
+
+local fontstreams = fonts.hashes.streams
+
+local report_fonts = logs.reporter("backend","fonts")
+local trace_fonts = false
+local trace_detail = false
+
+trackers.register("backend.pdf.fonts",function(v) trace_fonts = v end)
+
+local readers = fonts.handlers.otf.readers
+local getinfo = readers.getinfo
+
+local setposition = utilities.files.setposition
+local readstring = utilities.files.readstring
+local openfile = utilities.files.open
+local closefile = utilities.files.close
+
+-- needs checking: signed vs unsigned
+
+local tocardinal1 = char
+
+local function tocardinal2(n)
+ return char(extract(n,8,8),extract(n,0,8))
+end
+
+local function tocardinal3(n)
+ return char(extract(n,16,8),extract(n,8,8),extract(n,0,8))
+end
+
+local function tocardinal4(n)
+ return char(extract(n,24,8),extract(n,16,8),extract(n,8,8),extract(n,0,8))
+end
+
+local function tointeger2(n)
+ return char(extract(n,8,8),extract(n,0,8))
+end
+
+local function tointeger3(n)
+ return char(extract(n,16,8),extract(n,8,8),extract(n,0,8))
+end
+
+local function tointeger4(n)
+ return char(extract(n,24,8),extract(n,16,8),extract(n,8,8),extract(n,0,8))
+end
+
+local function tocardinal8(n)
+ local l = idiv(n,0x100000000)
+ local r = n % 0x100000000
+ return char(extract(l,24,8),extract(l,16,8),extract(l,8,8),extract(l,0,8),
+ extract(r,24,8),extract(r,16,8),extract(r,8,8),extract(r,0,8))
+end
+
+-- A couple of shared helpers.
+
+local tounicodedictionary, widtharray, collectindices, subsetname, includecidset, tocidsetdictionary
+
+do
+
+ -- Because we supply tounicodes ourselves we only use bfchar mappings (as in the
+ -- backend). In fact, we can now no longer pass the tounicodes to the frontend but
+ -- pick them up from the descriptions.
+
+ local f_mapping = formatters["<%04X> <%s>"]
+
+ local tounicode = fonts.mappings.tounicode
+
+local tounicode_template = [[
+%%!PS-Adobe-3.0 Resource-CMap
+%%%%DocumentNeededResources: ProcSet (CIDInit)
+%%%%IncludeResource: ProcSet (CIDInit)
+%%%%BeginResource: CMap (TeX-%s-0)
+%%%%Title: (TeX-%s-0 TeX %s 0)|
+%%%%Version: 1.000
+%%%%EndComments
+/CIDInit /ProcSet findresource begin
+ 12 dict begin
+ begincmap
+ /CIDSystemInfo
+ << /Registry (TeX) /Ordering (%s) /Supplement 0 >>
+ def
+ /CMapName
+ /TeX-Identity-%s
+ def
+ /CMapType
+ 2
+ def
+ 1 begincodespacerange
+ <0000> <FFFF>
+ endcodespacerange
+ %i beginbfchar
+
+%s
+
+ endbfchar
+ endcmap
+ CMapName currentdict /CMap defineresource pop
+ end
+end
+%%%%EndResource
+%%%%EOF]]
+
+ tounicodedictionary = function(details,indices,maxindex,name)
+ local mapping = { }
+ local length = 0
+ if maxindex > 0 then
+ for index=1,maxindex do
+ local data = indices[index]
+ if data then
+ length = length + 1
+ local unicode = data.unicode
+ if unicode then
+ unicode = tounicode(unicode)
+ else
+ unicode = "FFFD"
+ end
+ mapping[length] = f_mapping(index,unicode)
+ end
+ end
+ end
+ local name = gsub(name,"%+","-") -- like luatex does
+ local blob = format(tounicode_template,name,name,name,name,name,length,concat(mapping,"\n"))
+ return blob
+ end
+
+ widtharray = function(details,indices,maxindex,units)
+ local widths = pdfarray()
+ local length = 0
+ local factor = 10000 / units
+ if maxindex > 0 then
+ local lastindex = -1
+ local sublist = nil
+ for index=1,maxindex do
+ local data = indices[index]
+ if data then
+ local width = data.width -- hm, is inaccurate for cff, so take from elsewhere
+ if width then
+ -- width = round(width * 10000 / units) / 10
+ width = round(width * factor) / 10
+ else
+ width = 0
+ end
+ if index == lastindex + 1 then
+ sublist[#sublist+1] = width
+ else
+ if sublist then
+ length = length + 1
+ widths[length] = sublist
+ end
+ sublist = pdfarray { width }
+ length = length + 1
+ widths[length] = index
+ end
+ lastindex = index
+ end
+ end
+ length = length + 1
+ widths[length] = sublist
+ end
+ return widths
+ end
+
+ collectindices = function(descriptions,indices)
+ local minindex = 0xFFFF
+ local maxindex = 0
+ local reverse = { }
+ -- todo: already at definition time trigger copying streams
+ -- and add extra indices ... first i need a good example of
+ -- a clash
+ -- for unicode, data in next, descriptions do
+ -- local i = data.index or unicode
+ -- if reverse[i] then
+ -- print("CLASH")
+ -- else
+ -- reverse[i] = data
+ -- end
+ -- end
+ for unicode, data in next, descriptions do
+ reverse[data.index or unicode] = data
+ end
+ for index in next, indices do
+ if index > maxindex then
+ maxindex = index
+ end
+ if index < minindex then
+ minindex = index
+ end
+ indices[index] = reverse[index]
+ end
+ if minindex > maxindex then
+ minindex = maxindex
+ end
+ return indices, minindex, maxindex
+ end
+
+ includecidset = false
+
+ tocidsetdictionary = function(indices,min,max)
+ if includecidset then
+ local b = { }
+ local m = idiv(max+7,8)
+ for i=0,max do
+ b[i] = 0
+ end
+ for i=min,max do
+ if indices[i] then
+ local bi = idiv(i,8)
+ local ni = i % 8
+ b[bi] = bor(b[bi],lshift(1,7-ni))
+ end
+ end
+ b = char(unpack(b,0,#b))
+ return pdfreference(pdfflushstreamobject(b))
+ end
+ end
+
+ -- Actually we can use the same as we only embed once.
+
+ -- subsetname = function(name)
+ -- return "CONTEXT" .. name
+ -- end
+
+ local prefixes = { } -- todo: set fixed one
+
+ subsetname = function(name)
+ local prefix
+ while true do
+ prefix = utfchar(random(65,90),random(65,90),random(65,90),random(65,90),random(65,90),random(65,90))
+ if not prefixes[prefix] then
+ prefixes[prefix] = true
+ break
+ end
+ end
+ return prefix .. "+" .. name
+ end
+
+end
+
+-- Map file mess.
+
+local loadmapfile, loadmapline, getmapentry do
+
+ -- We only need to pick up the filename and optionally the enc file
+ -- as we only use them for old school virtual math fonts. We might as
+ -- we drop this completely.
+
+ local find, match, splitlines = string.find, string.match, string.splitlines
+
+
+ local mappings = { }
+
+ loadmapline = function(n)
+ local name, fullname, encfile, pfbfile = match(n,"(%S+)%s+(%S+).-<(.-%.enc).-<(.-%.pfb)")
+ if name then
+ mappings[name] = { fullname, encfile, pfbfile }
+ end
+ end
+
+ loadmapfile = function(n)
+ local okay, data = resolvers.loadbinfile(n,"map")
+ if okay and data then
+ data = splitlines(data)
+ for i=1,#data do
+ local d = data[i]
+ if d ~= "" and not find(d,"^[#%%]") then
+ loadmapline(d)
+ end
+ end
+ end
+ end
+
+ getmapentry = function(n)
+ local n = file.nameonly(n)
+ local m = mappings[n]
+ if m then
+ local encfile = m[2]
+ local encoding = fonts.encodings.load(encfile)
+ if not encoding then
+ return
+ end
+ local pfbfile = resolvers.find_file(m[3],"pfb")
+ if not pfbfile or pfbfile == "" then
+ return
+ end
+ return encoding, pfbfile, encfile
+ end
+ end
+
+end
+
+-- The three writers: opentype, truetype and type1.
+
+local mainwriters = { }
+
+do
+
+ -- advh = os2.ascender - os2.descender
+ -- tsb = default_advh - os2.ascender
+
+ -- truetype has the following tables:
+
+ -- head : mandate
+ -- hhea : mandate
+ -- vhea : mandate
+ -- hmtx : mandate
+ -- maxp : mandate
+ -- glyf : mandate
+ -- loca : mandate
+ --
+ -- cvt : if needed (but we flatten)
+ -- fpgm : if needed (but we flatten)
+ -- prep : if needed (but we flatten)
+ -- PCLT : if needed (but we flatten)
+ --
+ -- name : not needed for T2: backend does that
+ -- post : not needed for T2: backend does that
+ -- OS/2 : not needed for T2: backend does that
+ -- cmap : not needed for T2: backend does that
+
+ local streams = utilities.streams
+ local openstring = streams.openstring
+ local readcardinal2 = streams.readcardinal2
+ ----- readcardinal4 = streams.readcardinal4
+
+ local otfreaders = fonts.handlers.otf.readers
+
+ local function readcardinal4(f) -- this needs to be sorted out
+ local a = readcardinal2(f)
+ local b = readcardinal2(f)
+ if a and b then
+ return a * 0x10000 + b
+ end
+ end
+
+ -- -- --
+
+ local tablereaders = { }
+ local tablewriters = { }
+ local tablecreators = { }
+ local tableloaders = { }
+
+ local openfontfile, closefontfile, makefontfile, makemetadata do
+
+ local details = {
+ details = true,
+ platformnames = true,
+ platformextras = true,
+ }
+
+ -- .022 sec on luatex manual, neglectable:
+
+ -- local function checksum(data)
+ -- local s = openstring(data)
+ -- local n = 0
+ -- local d = #data
+ -- while true do
+ -- local c = readcardinal4(s)
+ -- if c then
+ -- n = (n + c) % 0x100000000
+ -- else
+ -- break
+ -- end
+ -- end
+ -- return n
+ -- end
+
+ local function checksum(data)
+ local s = openstring(data)
+ local n = 0
+ local d = #data
+ while true do
+ local a = readcardinal2(s)
+ local b = readcardinal2(s)
+ if b then
+ n = (n + a * 0x10000 + b) % 0x100000000
+ else
+ break
+ end
+ end
+ return n
+ end
+
+ openfontfile = function(details)
+ return {
+ offset = 0,
+ order = { },
+ used = { },
+ details = details,
+ streams = details.streams,
+ }
+ end
+
+ closefontfile = function(fontfile)
+ for k, v in next, fontfile do
+ fontfile[k] = nil -- so it can be collected asap
+ end
+ end
+
+ local metakeys = {
+ "uniqueid", "version",
+ "copyright", "license", "licenseurl",
+ "manufacturer", "vendorurl",
+ "family", "subfamily",
+ "typographicfamily", "typographicsubfamily",
+ "fullname", "postscriptname",
+ }
+
+ local template = [[
+<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
+ <x:xmpmeta xmlns:x="adobe:ns:meta/">
+ <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+ <rdf:Description rdf:about="" xmlns:pdfx="http://ns.adobe.com/pdfx/1.3/">
+
+%s
+
+ </rdf:Description>
+ </rdf:RDF>
+ </x:xmpmeta>
+<?xpacket end="w"?>]]
+
+ makemetadata = function(fontfile)
+ local names = fontfile.streams.names
+ local list = { }
+ local f_name = formatters["<pdfx:%s>%s</pdfx:%s>"]
+ for i=1,#metakeys do
+ local m = metakeys[i]
+ local n = names[m]
+ if n then
+ list[#list+1] = f_name(m,n,m)
+ end
+ end
+ return format(template,concat(list,"\n"))
+ end
+
+ makefontfile = function(fontfile)
+ local order = fontfile.order
+ local used = fontfile.used
+ local count = 0
+ for i=1,#order do
+ local tag = order[i]
+ local data = fontfile[tag]
+ if data and #data > 0 then
+ count = count + 1
+ else
+ fontfile[tag] = false
+ end
+ end
+ local offset = 12 + (count * 16)
+ local headof = 0
+ local list = {
+ "" -- placeholder
+ }
+ local i = 1
+ local k = 0
+ while i <= count do
+ i = lshift(i,1)
+ k = k + 1
+ end
+ local searchrange = lshift(i,3)
+ local entryselector = k - 1
+ local rangeshift = lshift(count,4) - lshift(i,3)
+ local index = {
+ tocardinal4(0x00010000), -- tables.version
+ tocardinal2(count),
+ tocardinal2(searchrange),
+ tocardinal2(entryselector),
+ tocardinal2(rangeshift),
+ }
+ --
+ local ni = #index
+ local nl = #list
+ for i=1,#order do
+ local tag = order[i]
+ local data = fontfile[tag]
+ if data then
+ local csum = checksum(data)
+ local dlength = #data
+ local length = idiv(dlength+3,4) * 4
+ local padding = length - dlength
+ nl = nl + 1 ; list[nl] = data
+ for i=1,padding do
+ nl = nl + 1 ; list[nl] = "\0"
+ end
+ if #tag == 3 then
+ tag = tag .. " "
+ end
+ ni = ni + 1 ; index[ni] = tag -- must be 4 chars
+ ni = ni + 1 ; index[ni] = tocardinal4(csum)
+ ni = ni + 1 ; index[ni] = tocardinal4(offset)
+ ni = ni + 1 ; index[ni] = tocardinal4(dlength)
+ used[i] = offset -- not used
+ if tag == "head" then
+ headof = offset
+ end
+ offset = offset + length
+ end
+ end
+ list[1] = concat(index)
+ local off = #list[1] + headof + 1 + 8
+ list = concat(list)
+ local csum = (0xB1B0AFBA - checksum(list)) % 0x100000000
+ list = sub(list,1,off-1) .. tocardinal4(csum) .. sub(list,off+4,#list)
+ return list
+ end
+
+ local function register(fontfile,name)
+ local u = fontfile.used
+ local o = fontfile.order
+ if not u[name] then
+ o[#o+1] = name
+ u[name] = true
+ end
+ end
+
+ local function create(fontfile,name)
+ local t = { }
+ fontfile[name] = t
+ return t
+ end
+
+ local function write(fontfile,name)
+ local t = fontfile[name]
+ if not t then
+ return
+ end
+ register(fontfile,name)
+ if type(t) == "table" then
+ if t[0] then
+ fontfile[name] = concat(t,"",0,#t)
+ elseif #t > 0 then
+ fontfile[name] = concat(t)
+ else
+ fontfile[name] = false
+ end
+ end
+ end
+
+ tablewriters.head = function(fontfile)
+ register(fontfile,"head")
+ local t = fontfile.streams.fontheader
+ fontfile.head = concat {
+ tocardinal4(t.version),
+ tocardinal4(t.fontversionnumber),
+ tocardinal4(t.checksum),
+ tocardinal4(t.magic),
+ tocardinal2(t.flags),
+ tocardinal2(t.units),
+ tocardinal8(t.created),
+ tocardinal8(t.modified),
+ tocardinal2(t.xmin),
+ tocardinal2(t.ymin),
+ tocardinal2(t.xmax),
+ tocardinal2(t.ymax),
+ tocardinal2(t.macstyle),
+ tocardinal2(t.smallpixels),
+ tocardinal2(t.directionhint),
+ tocardinal2(t.indextolocformat),
+ tocardinal2(t.glyphformat),
+ }
+ end
+
+ tablewriters.hhea = function(fontfile)
+ register(fontfile,"hhea")
+ local t = fontfile.streams.horizontalheader
+ local n = t and fontfile.nofglyphs or 0
+ fontfile.hhea = concat {
+ tocardinal4(t.version),
+ tocardinal2(t.ascender),
+ tocardinal2(t.descender),
+ tocardinal2(t.linegap),
+ tocardinal2(t.maxadvancewidth),
+ tocardinal2(t.minleftsidebearing),
+ tocardinal2(t.minrightsidebearing),
+ tocardinal2(t.maxextent),
+ tocardinal2(t.caretsloperise),
+ tocardinal2(t.caretsloperun),
+ tocardinal2(t.caretoffset),
+ tocardinal2(t.reserved_1),
+ tocardinal2(t.reserved_2),
+ tocardinal2(t.reserved_3),
+ tocardinal2(t.reserved_4),
+ tocardinal2(t.metricdataformat),
+ tocardinal2(n) -- t.nofmetrics
+ }
+ end
+
+ tablewriters.vhea = function(fontfile)
+ local t = fontfile.streams.verticalheader
+ local n = t and fontfile.nofglyphs or 0
+ register(fontfile,"vhea")
+ fontfile.vhea = concat {
+ tocardinal4(t.version),
+ tocardinal2(t.ascender),
+ tocardinal2(t.descender),
+ tocardinal2(t.linegap),
+ tocardinal2(t.maxadvanceheight),
+ tocardinal2(t.mintopsidebearing),
+ tocardinal2(t.minbottomsidebearing),
+ tocardinal2(t.maxextent),
+ tocardinal2(t.caretsloperise),
+ tocardinal2(t.caretsloperun),
+ tocardinal2(t.caretoffset),
+ tocardinal2(t.reserved_1),
+ tocardinal2(t.reserved_2),
+ tocardinal2(t.reserved_3),
+ tocardinal2(t.reserved_4),
+ tocardinal2(t.metricdataformat),
+ tocardinal2(n) -- t.nofmetrics
+ }
+ end
+
+ tablewriters.maxp = function(fontfile)
+ register(fontfile,"maxp")
+ local t = fontfile.streams.maximumprofile
+ local n = fontfile.nofglyphs
+ -- if fontfile.streams.cffinfo then
+ -- error
+ -- end
+ fontfile.maxp = concat {
+ tocardinal4(0x00010000),
+ tocardinal2(n),
+ tocardinal2(t.points),
+ tocardinal2(t.contours),
+ tocardinal2(t.compositepoints),
+ tocardinal2(t.compositecontours),
+ tocardinal2(t.zones),
+ tocardinal2(t.twilightpoints),
+ tocardinal2(t.storage),
+ tocardinal2(t.functiondefs),
+ tocardinal2(t.instructiondefs),
+ tocardinal2(t.stackelements),
+ tocardinal2(t.sizeofinstructions),
+ tocardinal2(t.componentelements),
+ tocardinal2(t.componentdepth),
+ }
+ end
+
+ tablecreators.loca = function(fontfile) return create(fontfile,"loca") end
+ tablewriters .loca = function(fontfile) return write (fontfile,"loca") end
+
+ tablecreators.glyf = function(fontfile) return create(fontfile,"glyf") end
+ tablewriters .glyf = function(fontfile) return write (fontfile,"glyf") end
+
+ tablecreators.hmtx = function(fontfile) return create(fontfile,"hmtx") end
+ tablewriters .hmtx = function(fontfile) return write (fontfile,"hmtx") end
+
+ tablecreators.vmtx = function(fontfile) return create(fontfile,"vmtx") end
+ tablewriters .vmtx = function(fontfile) return write (fontfile,"vmtx") end
+
+ tableloaders .cmap = function(fontfile) return read (fontfile,"cmap") end
+ tablewriters .cmap = function(fontfile) return write (fontfile,"cmap") end
+
+ tableloaders .name = function(fontfile) return read (fontfile,"name") end
+ tablewriters .name = function(fontfile) return write (fontfile,"name") end
+
+ tableloaders .post = function(fontfile) return read (fontfile,"post") end
+ tablewriters .post = function(fontfile) return write (fontfile,"post") end
+
+ end
+
+ mainwriters["truetype"] = function(details)
+ --
+ local fontfile = openfontfile(details)
+ local basefontname = details.basefontname
+ local streams = details.streams
+ local blobs = streams.streams
+ local fontheader = streams.fontheader
+ local horizontalheader = streams.horizontalheader
+ local verticalheader = streams.verticalheader
+ local maximumprofile = streams.maximumprofile
+ local names = streams.names
+ local descriptions = details.rawdata.descriptions
+ local metadata = details.rawdata.metadata
+ local indices = details.indices
+ local metabbox = { fontheader.xmin, fontheader.ymin, fontheader.xmax, fontheader.ymax }
+ local indices,
+ minindex,
+ maxindex = collectindices(descriptions,indices)
+ local glyphstreams = tablecreators.glyf(fontfile)
+ local locations = tablecreators.loca(fontfile)
+ local horizontals = tablecreators.hmtx(fontfile)
+ local verticals = tablecreators.vmtx(fontfile)
+ --
+ local zero2 = tocardinal2(0)
+ local zero4 = tocardinal4(0)
+ --
+ local horizontal = horizontalheader.nofmetrics > 0
+ local vertical = verticalheader.nofmetrics > 0
+ --
+ local streamoffset = 0
+ local lastoffset = zero4
+ local g, h, v = 0, 0, 0
+ --
+ -- todo: locate notdef
+ --
+ if minindex > 0 then
+ local blob = blobs[0]
+ if blob and #blob > 0 then
+ locations[0] = lastoffset
+ g = g + 1 ; glyphstreams[g] = blob
+ h = h + 1 ; horizontals [h] = zero4
+ if vertical then
+ v = v + 1 ; verticals[v] = zero4
+ end
+ streamoffset = streamoffset + #blob
+ lastoffset = tocardinal4(streamoffset)
+ else
+ print("missing .notdef")
+ end
+ -- todo: use a rep for h/v
+ for index=1,minindex-1 do
+ locations[index] = lastoffset
+ h = h + 1 ; horizontals[h] = zero4
+ if vertical then
+ v = v + 1 ; verticals[v] = zero4
+ end
+ end
+ end
+ for index=minindex,maxindex do
+ locations[index] = lastoffset
+ local data = indices[index]
+ if data then
+ local blob = blobs[index] -- we assume padding
+ if blob and #blob > 0 then
+ g = g + 1 ; glyphstreams[g] = blob
+ h = h + 1 ; horizontals [h] = tocardinal2(data.width or 0)
+ h = h + 1 ; horizontals [h] = tocardinal2(data.boundingbox[1])
+ if vertical then
+ v = v + 1 ; verticals[v] = tocardinal2(data.height or 0)
+ v = v + 1 ; verticals[v] = tocardinal2(data.boundingbox[3])
+ end
+ streamoffset = streamoffset + #blob
+ lastoffset = tocardinal4(streamoffset)
+ else
+ h = h + 1 ; horizontals[h] = zero4
+ if vertical then
+ v = v + 1 ; verticals[v] = zero4
+ end
+ print("missing blob for index",index)
+ end
+ else
+ h = h + 1 ; horizontals[h] = zero4
+ if vertical then
+ v = v + 1 ; verticals[v] = zero4
+ end
+ end
+ end
+ locations[maxindex+1] = lastoffset -- cf spec
+ --
+ local nofglyphs = maxindex + 1 -- include zero
+ --
+ fontheader.checksum = 0
+ fontheader.indextolocformat = 1
+ maximumprofile.nofglyphs = nofglyphs
+ --
+ fontfile.format = "tff"
+ fontfile.basefontname = basefontname
+ fontfile.nofglyphs = nofglyphs
+ --
+ tablewriters.head(fontfile)
+ tablewriters.hhea(fontfile)
+ if vertical then
+ tablewriters.vhea(fontfile)
+ end
+ tablewriters.maxp(fontfile)
+
+ tablewriters.loca(fontfile)
+ tablewriters.glyf(fontfile)
+
+ tablewriters.hmtx(fontfile)
+ if vertical then
+ tablewriters.vmtx(fontfile)
+ end
+ --
+ local fontdata = makefontfile(fontfile)
+ local fontmeta = makemetadata(fontfile)
+ --
+ fontfile = closefontfile(fontfile)
+ --
+ local units = metadata.units
+ local basefont = pdfconstant(basefontname)
+ local widths = widtharray(details,indices,maxindex,units)
+ local object = details.objectnumber
+ local tounicode = tounicodedictionary(details,indices,maxindex,basefontname)
+ local tocidset = tocidsetdictionary(indices,minindex,maxindex)
+ local metabbox = metadata.boundingbox or { 0, 0, 0, 0 }
+ local fontbbox = pdfarray { unpack(metabbox) }
+ local ascender = metadata.ascender
+ local descender = metadata.descender
+ local capheight = metadata.capheight or fontbbox[4]
+ local stemv = metadata.weightclass
+ local italicangle = metadata.italicangle
+ local xheight = metadata.xheight or fontbbox[4]
+ --
+ if stemv then
+ stemv = (stemv/65)^2 + 50
+ end
+ --
+ local function scale(n)
+ if n then
+ return round((n) * 10000 / units) / 10
+ else
+ return 0
+ end
+ end
+ --
+ local reserved = pdfreserveobject()
+ local child = pdfdictionary {
+ Type = pdfconstant("Font"),
+ Subtype = pdfconstant("CIDFontType2"),
+ BaseFont = basefont,
+ FontDescriptor = pdfreference(reserved),
+ W = pdfreference(pdfflushobject(widths)),
+ CIDToGIDMap = pdfconstant("Identity"),
+ CIDSystemInfo = pdfdictionary {
+ Registry = pdfstring("Adobe"),
+ Ordering = pdfstring("Identity"),
+ Supplement = 0,
+ }
+ }
+ local descendants = pdfarray {
+ pdfreference(pdfflushobject(child)),
+ }
+ local descriptor = pdfdictionary {
+ Type = pdfconstant("FontDescriptor"),
+ FontName = basefont,
+ Flags = 4,
+ FontBBox = fontbbox,
+ Ascent = scale(ascender),
+ Descent = scale(descender),
+ ItalicAngle = round(italicangle or 0),
+ CapHeight = scale(capheight),
+ StemV = scale(stemv),
+ XHeight = scale(xheight),
+ FontFile2 = pdfreference(pdfflushstreamobject(fontdata)),
+ CIDSet = tocidset,
+ Metadata = fontmeta and pdfreference(pdfflushstreamobject(fontmeta)) or nil,
+ }
+ local parent = pdfdictionary {
+ Type = pdfconstant("Font"),
+ Subtype = pdfconstant("Type0"),
+ Encoding = pdfconstant(details.properties.writingmode == "vertical" and "Identity-V" or "Identity-H"),
+ BaseFont = basefont,
+ DescendantFonts = descendants,
+ ToUnicode = pdfreference(pdfflushstreamobject(tounicode)),
+ }
+ pdfflushobject(reserved,descriptor)
+ pdfflushobject(object,parent)
+ --
+ -- if trace_detail then
+ -- local name = "temp.ttf"
+ -- report_fonts("saving %a",name)
+ -- io.savedata(name,fontdata)
+ -- inspect(fonts.handlers.otf.readers.loadfont(name))
+ -- end
+ --
+ end
+
+ do
+ -- todo : cff2
+
+ local details = {
+ details = true,
+ platformnames = true,
+ platformextras = true,
+ }
+
+ tablecreators.cff = function(fontfile)
+ fontfile.charstrings = { }
+ fontfile.charmappings = { }
+ fontfile.cffstrings = { }
+ fontfile.cffhash = { }
+ return fontfile.charstrings , fontfile.charmappings
+ end
+
+ local todictnumber, todictreal, todictinteger, todictoffset do
+
+ local maxnum = 0x7FFFFFFF
+ local minnum = - 0x7FFFFFFF - 1
+ local epsilon = 1.0e-5
+
+ local int2tag = "\28"
+ local int4tag = "\29"
+ local realtag = "\30"
+
+ todictinteger = function(n)
+ if not n then
+ return char(band(139,0xFF))
+ elseif n >= -107 and n <= 107 then
+ return char(band(n + 139,0xFF))
+ elseif n >= 108 and n <= 1131 then
+ n = 0xF700 + n - 108
+ return char(band(rshift(n,8),0xFF),band(n,0xFF))
+ elseif n >= -1131 and n <= -108 then
+ n = 0xFB00 - n - 108
+ return char(band(rshift(n,8),0xFF),band(n,0xFF))
+ elseif n >= -32768 and n <= 32767 then
+ -- return int2tag .. tointeger2(n)
+ return char(28,extract(n,8,8),extract(n,0,8))
+ else
+ -- return int4tag .. tointeger4(n)
+ return char(29,extract(n,24,8),extract(n,16,8),extract(n,8,8),extract(n,0,8))
+ end
+ end
+
+ -- -- not called that often
+ --
+ -- local encoder = readers.cffencoder
+ --
+ -- todictinteger = function(n)
+ -- if not n then
+ -- return encoder[0]
+ -- elseif n >= -1131 and n <= 1131 then
+ -- return encoder[n]
+ -- elseif n >= -32768 and n <= 32767 then
+ -- -- return int2tag .. tointeger2(n)
+ -- return char(28,extract(n,8,8),extract(n,0,8))
+ -- else
+ -- -- return int4tag .. tointeger4(n)
+ -- return char(29,extract(n,24,8),extract(n,16,8),extract(n,8,8),extract(n,0,8))
+ -- end
+ -- end
+
+ todictoffset = function(n)
+ return int4tag .. tointeger4(n)
+ end
+
+ local e = false
+ local z = byte("0")
+ local dp = 10
+ local ep = 11
+ local em = 12
+ local mn = 14
+ local es = 15
+
+ local fg = formatters["%g"]
+
+ todictreal = function(v)
+ local s = fg(v)
+ local t = { [0] = realtag }
+ local n = 0
+ for s in gmatch(s,".") do
+ if s == "e" or s == "E" then
+ e = true
+ elseif s == "+" then
+ -- skip
+ elseif s == "-" then
+ n = n + 1
+ if e then
+ t[n] = em
+ e = false
+ else
+ t[n] = mn
+ end
+ else
+ if e then
+ n = n + 1
+ t[n] = ep
+ e = false
+ end
+ n = n + 1
+ if s == "." then
+ t[n] = dp
+ else
+ t[n] = byte(s) - z
+ end
+ end
+ end
+ n = n + 1
+ t[n] = es
+ if (n % 2) ~= 0 then
+ n = n + 1
+ t[n] = es
+ end
+ local j = 0
+ for i=1,n,2 do
+ j = j + 1
+ t[j] = char(t[i]*0x10+t[i+1])
+ end
+ t = concat(t,"",0,j)
+ return t
+ end
+
+ todictnumber = function(n)
+ if not n or n == 0 then
+ return todictinteger(0)
+ elseif (n > maxnum or n < minnum or (abs(n - round(n)) > epsilon)) then
+ return todictreal(n)
+ else
+ return todictinteger(n)
+ end
+ end
+
+ end
+
+ local todictkey = char
+
+ local function todictstring(fontfile,value)
+ if not value then
+ value = ""
+ end
+ local s = fontfile.cffstrings
+ local h = fontfile.cffhash
+ local n = h[value]
+ if not n then
+ n = #s + 1
+ s[n] = value
+ h[value] = n
+ end
+ return todictinteger(390+n)
+ end
+
+ local function todictboolean(b)
+ return todictinteger(b and 1 or 0)
+ end
+
+ local function todictdeltas(t)
+ local r = { }
+ for i=1,#t do
+ r[i] = todictnumber(t[i]-(t[i-1] or 0))
+ end
+ return concat(r)
+ end
+
+ local function todictarray(t)
+ local r = { }
+ for i=1,#t do
+ r[i] = todictnumber(t[i])
+ end
+ return concat(r)
+ end
+
+ local function writestring(target,source,offset,what)
+ target[#target+1] = source
+ -- report_fonts("string : %-11s %06i # %05i",what,offset,#source)
+ return offset + #source
+ end
+
+ local function writetable(target,source,offset,what)
+ source = concat(source)
+ target[#target+1] = source
+ -- report_fonts("table : %-11s %06i # %05i",what,offset,#source)
+ return offset + #source
+ end
+
+ local function writeindex(target,source,offset,what)
+ local n = #source
+ local t = #target
+ t = t + 1 ; target[t] = tocardinal2(n)
+ if n > 0 then
+ local data = concat(source)
+ local size = #data -- assume the worst
+ local offsetsize, tocardinal
+ if size < 0xFF then
+ offsetsize, tocardinal = 1, tocardinal1
+ elseif size < 0xFFFF then
+ offsetsize, tocardinal = 2, tocardinal2
+ elseif size < 0xFFFFFF then
+ offsetsize, tocardinal = 3, tocardinal3
+ elseif size < 0xFFFFFFFF then
+ offsetsize, tocardinal = 4, tocardinal4
+ end
+ -- report_fonts("index : %-11s %06i # %05i (%i entries with offset size %i)",what,offset,#data,n,offsetsize)
+ offset = offset + 2 + 1 + (n + 1) * offsetsize + size
+ -- bytes per offset
+ t = t + 1 ; target[t] = tocardinal1(offsetsize)
+ -- list of offsets (one larger for length calculation)
+ local offset = 1 -- mandate
+ t = t + 1 ; target[t] = tocardinal(offset)
+ for i=1,n do
+ offset = offset + #source[i]
+ t = t + 1 ; target[t] = tocardinal(offset)
+ end
+ t = t + 1 ; target[t] = data
+ else
+ -- report_fonts("index : %-11s %06i # %05i (no entries)",what,offset,0)
+ offset = offset + 2
+ end
+ -- print("offset",offset,#concat(target))
+ return offset
+ end
+
+ tablewriters.cff = function(fontfile)
+ --
+ local streams = fontfile.streams
+ local cffinfo = streams.cffinfo or { }
+ local names = streams.names or { }
+ local fontheader = streams.fontheader or { }
+ local basefontname = fontfile.basefontname
+ --
+ local offset = 0
+ local dictof = 0
+ local target = { }
+ --
+ local charstrings = fontfile.charstrings
+ local nofglyphs = #charstrings + 1
+ local fontmatrix = { 0.001, 0, 0, 0.001, 0, 0 } -- todo
+ local fontbbox = fontfile.fontbbox
+ local defaultwidth = cffinfo.defaultwidth or 0
+ local nominalwidth = cffinfo.nominalwidth or 0
+ local bluevalues = cffinfo.bluevalues
+ local otherblues = cffinfo.otherblues
+ local familyblues = cffinfo.familyblues
+ local familyotherblues = cffinfo.familyotherblues
+ local bluescale = cffinfo.bluescale
+ local blueshift = cffinfo.blueshift
+ local bluefuzz = cffinfo.bluefuzz
+ local stdhw = cffinfo.stdhw
+ local stdvw = cffinfo.stdvw
+ --
+-- bluescale = 0.039625
+-- blueshift = 7
+-- bluefuzz = 1
+-- defaultwidth = 500
+-- nominalwidth = 696
+-- stdhw = { 28, 36, 42, 48, 60 }
+-- stdvw = { 40, 60, 66, 72, 76, 80, 88, 94 }
+ if defaultwidth == 0 then defaultwidth = nil end
+ if nomimalwidth == 0 then nominalwidth = nil end
+ if bluevalues then bluevalues = todictarray(bluevalues) end
+ if otherblues then otherblues = todictarray(otherblues) end
+ if familyblues then familyblues = todictarray(familyblues) end
+ if familyotherblues then familyotherblues = todictarray(familyotherblues) end
+ if bluescale then bluescale = todictnumber(bluescale) end
+ if blueshift then blueshift = todictnumber(blueshift) end
+ if bluefuzz then bluefuzz = todictnumber(bluefuzz) end
+-- if stdhw then stdhw = todictarray(stdhw) end
+-- if stdvw then stdvw = todictarray(stdvw) end
+if stdhw then stdhw = todictdeltas(stdhw) end
+if stdvw then stdvw = todictdeltas(stdvw) end
+ --
+ local fontversion = todictstring(fontfile,fontheader.fontversion or "uknown version")
+ local familyname = todictstring(fontfile,cffinfo.familyname or names.family or basefontname)
+ local fullname = todictstring(fontfile,cffinfo.fullname or basefontname)
+ local weight = todictstring(fontfile,cffinfo.weight or "Normal")
+ local fontbbox = todictarray(fontbbox)
+ local strokewidth = todictnumber(cffinfo.strokewidth)
+ local monospaced = todictboolean(cffinfo.monospaced)
+ local italicangle = todictnumber(cffinfo.italicangle)
+ local underlineposition = todictnumber(cffinfo.underlineposition)
+ local underlinethickness = todictnumber(cffinfo.underlinethickness)
+ local charstringtype = todictnumber(2)
+ local fontmatrix = todictarray(fontmatrix)
+ local ros = todictstring(fontfile,"Adobe") -- registry
+ .. todictstring(fontfile,"Identity") -- identity
+ .. todictnumber(0) -- supplement
+ local cidcount = todictnumber(fontfile.nofglyphs)
+ local fontname = todictstring(fontfile,basefontname)
+ local fdarrayoffset = todictoffset(0)
+ local fdselectoffset = todictoffset(0)
+ local charstringoffset = todictoffset(0)
+ local charsetoffset = todictoffset(0)
+ local privateoffset = todictoffset(0)
+ --
+ local defaultwidthx = todictnumber(defaultwidth)
+ local nominalwidthx = todictnumber(nominalwidth)
+ local private = ""
+ .. (defaultwidthx and (defaultwidthx .. todictkey(20)) or "")
+ .. (nominalwidthx and (nominalwidthx .. todictkey(21)) or "")
+ .. (bluevalues and (bluevalues .. todictkey(6)) or "")
+ .. (otherblues and (otherblues .. todictkey(7)) or "")
+ .. (familyblues and (familyblues .. todictkey(8)) or "")
+ .. (familyotherblues and (familyotherblues .. todictkey(9)) or "")
+ .. (bluescale and (bluescale .. todictkey(12,9)) or "")
+ .. (blueshift and (blueshift .. todictkey(12,10)) or "")
+ .. (bluefuzz and (bluefuzz .. todictkey(12,11)) or "")
+ .. (stdhw and (stdhw .. todictkey(12,12)) or "")
+ .. (stdvw and (stdvw .. todictkey(12,13)) or "")
+ local privatesize = todictnumber(#private)
+ local privatespec = privatesize .. privateoffset
+ --
+ -- header (fixed @ 1)
+ --
+ local header =
+ tocardinal1(1) -- major
+ .. tocardinal1(0) -- minor
+ .. tocardinal1(4) -- header size
+ .. tocardinal1(4) -- offset size
+ --
+ offset = writestring(target,header,offset,"header")
+ --
+ -- name index (fixed @ 2) (has to be sorted)
+ --
+ local names = {
+ basefontname,
+ }
+ --
+ offset = writeindex(target,names,offset,"names")
+ --
+ -- topdict index (fixed @ 3)
+ --
+ local topvars =
+ charstringoffset .. todictkey(17)
+ .. charsetoffset .. todictkey(15)
+ .. fdarrayoffset .. todictkey(12,36)
+ .. fdselectoffset .. todictkey(12,37)
+ .. privatespec .. todictkey(18)
+ --
+ local topdict = {
+ ros .. todictkey(12,30) -- first
+ .. cidcount .. todictkey(12,34)
+ .. familyname .. todictkey( 3)
+ .. fullname .. todictkey( 2)
+ .. weight .. todictkey( 4)
+ .. fontbbox .. todictkey( 5)
+ .. monospaced .. todictkey(12, 1)
+ .. italicangle .. todictkey(12, 2)
+ .. underlineposition .. todictkey(12, 3)
+ .. underlinethickness .. todictkey(12, 4)
+ .. charstringtype .. todictkey(12, 6)
+ .. fontmatrix .. todictkey(12, 7)
+ .. strokewidth .. todictkey(12, 8)
+ .. topvars
+ }
+ --
+ offset = writeindex(target,topdict,offset,"topdict")
+ dictof = #target
+ --
+ -- string index (fixed @ 4)
+ --
+ offset = writeindex(target,fontfile.cffstrings,offset,"strings")
+ --
+ -- global subroutine index (fixed @ 5)
+ --
+ offset = writeindex(target,{},offset,"globals")
+ --
+ -- Encoding (cff1)
+ --
+ -- offset = writeindex(target,{},offset,"encoding")
+ --
+ -- Charsets
+ --
+ charsetoffset = todictoffset(offset)
+ offset = writetable(target,fontfile.charmappings,offset,"charsets")
+ --
+ -- fdselect
+ --
+ local fdselect =
+ tocardinal1(3) -- format
+ .. tocardinal2(1) -- n of ranges
+ -- entry 1
+ .. tocardinal2(0) -- first gid
+ .. tocardinal1(0) -- fd index
+ -- entry 2
+-- .. tocardinal2(fontfile.sparsemax-1) -- sentinel
+ .. tocardinal2(fontfile.sparsemax) -- sentinel
+ --
+ fdselectoffset = todictoffset(offset)
+ offset = writestring(target,fdselect,offset,"fdselect")
+ --
+ -- charstrings
+ --
+ charstringoffset = todictoffset(offset)
+ offset = writeindex(target,charstrings,offset,"charstrings")
+ --
+ -- font dict
+ --
+ -- offset = writeindex(target,{},offset,"fontdict")
+ --
+ -- private
+ --
+ privateoffset = todictoffset(offset)
+ privatespec = privatesize .. privateoffset
+ offset = writestring(target,private,offset,"private")
+ --
+ local fdarray = {
+ fontname .. todictkey(12,38)
+ .. privatespec .. todictkey(18)
+ }
+ fdarrayoffset = todictoffset(offset)
+ offset = writeindex(target,fdarray,offset,"fdarray")
+ --
+ topdict = target[dictof]
+ topdict = sub(topdict,1,#topdict-#topvars)
+ topvars =
+ charstringoffset .. todictkey(17)
+ .. charsetoffset .. todictkey(15)
+ .. fdarrayoffset .. todictkey(12,36)
+ .. fdselectoffset .. todictkey(12,37)
+ .. privatespec .. todictkey(18)
+ target[dictof] = topdict .. topvars
+ --
+ target = concat(target)
+ -- if trace_detail then
+ -- local name = "temp.cff"
+ -- report_fonts("saving %a",name)
+ -- io.savedata(name,target)
+ -- inspect(fonts.handlers.otf.readers.cffcheck(name))
+ -- end
+ return target
+ end
+
+ end
+
+ -- todo: check widths (missing a decimal)
+
+ mainwriters["opentype"] = function(details)
+ --
+ local fontfile = openfontfile(details)
+ local basefontname = details.basefontname
+ local streams = details.streams
+ local blobs = streams.streams
+ local fontheader = streams.fontheader
+ local maximumprofile = streams.maximumprofile
+ local names = streams.names
+ local descriptions = details.rawdata.descriptions
+ local metadata = details.rawdata.metadata
+ local indices = details.indices
+ local metabbox = { fontheader.xmin, fontheader.ymin, fontheader.xmax, fontheader.ymax }
+ local indices,
+ minindex,
+ maxindex = collectindices(descriptions,indices)
+ local streamoffset = 0
+ local glyphstreams,
+ charmappings = tablecreators.cff(fontfile)
+ --
+ local zero2 = tocardinal2(0)
+ local zero4 = tocardinal4(0)
+ --
+ -- we need to locate notdef (or store its unicode someplace)
+ --
+ local blob = blobs[0] or "\14"
+ local sparsemax = 1
+ local lastoffset = zero4
+ glyphstreams[sparsemax] = blob
+ charmappings[sparsemax] = tocardinal1(0) -- format 0
+ streamoffset = streamoffset + #blob
+ lastoffset = tocardinal4(streamoffset)
+ if minindex == 0 then
+ minindex = 1
+ end
+ for index=minindex,maxindex do
+ if indices[index] then
+ local blob = blobs[index] or "\14"
+ sparsemax = sparsemax + 1
+ glyphstreams[sparsemax] = blob
+ charmappings[sparsemax] = tocardinal2(index)
+ streamoffset = streamoffset + #blob
+ lastoffset = tocardinal4(streamoffset)
+ end
+ end
+ --
+ fontfile.nofglyphs = maxindex + 1
+ fontfile.sparsemax = sparsemax
+ fontfile.format = "cff"
+ fontfile.basefontname = basefontname
+ fontfile.fontbbox = metabbox
+ --
+ local fontdata = tablewriters.cff(fontfile)
+ local fontmeta = makemetadata(fontfile)
+ --
+ fontfile = closefontfile(fontfile)
+ --
+ local units = fontheader.units or metadata.units
+ local basefont = pdfconstant(basefontname)
+ local widths = widtharray(details,indices,maxindex,units)
+ local object = details.objectnumber
+ local tounicode = tounicodedictionary(details,indices,maxindex,basefontname)
+ local tocidset = tocidsetdictionary(indices,minindex,maxindex)
+ local fontbbox = pdfarray { unpack(metabbox) }
+ local ascender = metadata.ascender or 0
+ local descender = metadata.descender or 0
+ local capheight = metadata.capheight or fontbbox[4]
+ local stemv = metadata.weightclass
+ local italicangle = metadata.italicangle
+ local xheight = metadata.xheight or fontbbox[4]
+ if stemv then
+ stemv = (stemv/65)^2 + 50
+ else
+-- stemv = 2
+ end
+ --
+ local function scale(n)
+ if n then
+ return round((n) * 10000 / units) / 10
+ else
+ return 0
+ end
+ end
+ --
+ local reserved = pdfreserveobject()
+ local child = pdfdictionary {
+ Type = pdfconstant("Font"),
+ Subtype = pdfconstant("CIDFontType0"),
+ BaseFont = basefont,
+ FontDescriptor = pdfreference(reserved),
+ W = pdfreference(pdfflushobject(widths)),
+ CIDSystemInfo = pdfdictionary {
+ Registry = pdfstring("Adobe"),
+ Ordering = pdfstring("Identity"),
+ Supplement = 0,
+ }
+ }
+ local descendants = pdfarray {
+ pdfreference(pdfflushobject(child)),
+ }
+ local fontstream = pdfdictionary {
+ Subtype = pdfconstant("CIDFontType0C"),
+ }
+ local descriptor = pdfdictionary {
+ Type = pdfconstant("FontDescriptor"),
+ FontName = basefont,
+ Flags = 4,
+ FontBBox = fontbbox,
+ Ascent = scale(ascender),
+ Descent = scale(descender),
+ ItalicAngle = round(italicangle or 0),
+ CapHeight = scale(capheight),
+ StemV = scale(stemv),
+ XHeight = scale(xheight),
+ CIDSet = tocidset,
+ FontFile3 = pdfreference(pdfflushstreamobject(fontdata,fontstream())),
+ Metadata = fontmeta and pdfreference(pdfflushstreamobject(fontmeta)) or nil,
+ }
+ local parent = pdfdictionary {
+ Type = pdfconstant("Font"),
+ Subtype = pdfconstant("Type0"),
+ Encoding = pdfconstant(details.properties.writingmode == "vertical" and "Identity-V" or "Identity-H"),
+ BaseFont = basefont,
+ DescendantFonts = descendants,
+ ToUnicode = pdfreference(pdfflushstreamobject(tounicode)),
+ }
+ pdfflushobject(reserved,descriptor)
+ pdfflushobject(object,parent)
+ end
+
+ mainwriters["type1"] = function(details)
+ local s = details.streams
+ local m = details.rawdata.metadata
+ if m then
+ local h = s.horizontalheader
+ local c = s.cffinfo
+ local n = s.names
+ h.ascender = m.ascender or h.ascender
+ h.descender = m.descender or h.descender
+ n.copyright = m.copyright or n.copyright
+ n.family = m.familyname or n.familyname
+ n.fullname = m.fullname or n.fullname
+ n.fontname = m.fontname or n.fontname
+ n.subfamily = m.subfamilyname or n.subfamilyname
+ n.version = m.version or n.version
+ setmetatableindex(h,m)
+ setmetatableindex(c,m)
+ setmetatableindex(n,m)
+ end
+ mainwriters["opentype"](details)
+ end
+
+ -- todo: map pdf glyphs onto companion type 3 font .. can be set of small
+ -- ones. maybe only private codes with proper tounicode
+
+ local methods = { }
+
+ function methods.pk(filename)
+ local resolution = 600
+ local widthfactor = resolution / 72
+ local scalefactor = 72 / resolution / 10
+ local pkfullname = resolvers.findpk(basedfontname,resolution)
+ if not pkfullname or pkfullname == "" then
+ return
+ end
+ local readers = fonts.handlers.tfm.readers
+ local result = readers.loadpk(pkfullname)
+ if not result or result.error then
+ return
+ end
+ return result.glyphs, widthfactor / 65536, scalefactor, readers.pktopdf
+ end
+
+ mainwriters["type3"] = function(details)
+ local properties = details.properties
+ local basefontname = details.basefontname or properties.name
+ local askedmethod = "pk"
+ local method = methods[askedmethod]
+ if not method then
+ return
+ end
+ local glyphs, widthfactor, scalefactor, glyphtopdf = method(basedfontname)
+ if not glyphs then
+ return
+ end
+ local parameters = details.parameters
+ local object = details.objectnumber
+ local factor = parameters.factor -- normally 1
+ local f_name = formatters["I%05i"]
+ local fontmatrix = pdfarray { scalefactor, 0, 0, scalefactor, 0, 0 }
+ local indices,
+ minindex,
+ maxindex = collectindices(details.fontdata.characters,details.indices)
+ local widths = pdfarray()
+ local differences = pdfarray()
+ local charprocs = pdfdictionary()
+ local basefont = pdfconstant(basefontname)
+ local llx, lly, urx, ury = 0, 0, 0, 0
+ for i=1,maxindex-minindex+1 do
+ widths[i] = 0
+ end
+ local d = 0
+ local lastindex = -0xFFFF
+ for index, data in sortedhash(indices) do
+ local name = f_name(index)
+ local glyph = glyphs[index]
+ if glyph then
+ local width = widthfactor * data.width
+ local stream, lx, ly, ux, uy = glyphtopdf(glyph,width)
+ if stream then
+ if index - 1 ~= lastindex then
+ d = d + 1 ; differences[d] = index
+ end
+ lastindex = index
+ d = d + 1 ; differences[d] = pdfconstant(name)
+ charprocs[name] = pdfreference(pdfflushstreamobject(stream))
+ widths[index-minindex+1] = width
+ if lx < llx then llx = lx end
+ if ux > urx then urx = ux end
+ if ly < lly then lly = ly end
+ if uy > ury then ury = uy end
+ end
+ end
+ end
+ local fontbbox = pdfarray { llx, lly, urx, ury }
+ local encoding = pdfdictionary {
+ Type = pdfconstant("Encoding"),
+ Differences = differences,
+ }
+ local tounicode = tounicodedictionary(details,indices,maxindex,basefontname)
+ local descriptor = pdfdictionary {
+ Type = pdfconstant("FontDescriptor"),
+ FontName = basefont,
+ Flags = 4,
+ FontBBox = fontbbox,
+ -- Ascent = scale(ascender),
+ -- Descent = scale(descender),
+ -- ItalicAngle = round(italicangle or 0),
+ -- CapHeight = scale(capheight),
+ -- StemV = scale(stemv),
+ -- XHeight = scale(xheight),
+ -- Metadata = fontmeta and pdfreference(pdfflushstreamobject(fontmeta)) or nil,
+ }
+ local parent = pdfdictionary {
+ Type = pdfconstant("Font"),
+ Subtype = pdfconstant("Type3"),
+ Name = basefont,
+ FontBBox = fontbbox,
+ FontMatrix = fontmatrix,
+ CharProcs = pdfreference(pdfflushobject(charprocs)),
+ Encoding = pdfreference(pdfflushobject(encoding)),
+ FirstChar = minindex,
+ LastChar = maxindex,
+ Widths = pdfreference(pdfflushobject(widths)),
+ FontDescriptor = pdfreference(pdfflushobject(descriptor)),
+ Resources = lpdf.procset(true),
+ ToUnicode = pdfreference(pdfflushstreamobject(tounicode)),
+ }
+ pdfflushobject(reserved,descriptor)
+ pdfflushobject(object,parent)
+ end
+
+end
+
+-- writingmode
+
+local usedfonts = fonts.hashes.identifiers -- for now
+local noffonts = 0
+
+-- The main injector.
+
+-- here we need to test for sharing otherwise we reserve too many
+-- objects
+
+local getstreamhash = fonts.handlers.otf.getstreamhash
+local loadstreamdata = fonts.handlers.otf.loadstreamdata
+
+-- we can actually now number upwards (so not use fontid in /F)
+
+local objects = setmetatableindex(function(t,k)
+ local v
+ if type(k) == "number" then
+ local h = getstreamhash(k)
+ v = rawget(t,h)
+ if not v then
+ v = pdfreserveobject()
+ t[h] = v
+ end
+ if trace_fonts then
+ report_fonts("font id %i bound to hash %s and object %i",k,h,v)
+ end
+ else
+ report_fonts("fatal error, hash %s asked but not used",k,h,v)
+ v = pdfreserveobject()
+ t[k] = v
+ end
+ return v
+end)
+
+local n = 0
+
+local names = setmetatableindex(function(t,k)
+ local v
+ if type(k) == "number" then
+ local h = getstreamhash(k)
+ v = rawget(t,h)
+ if not v then
+ n = n + 1
+ v = n
+ t[h] = v
+ end
+ if trace_fonts then
+ report_fonts("font id %i bound to hash %s and name %i",k,h,n)
+ end
+ end
+ t[k] = v
+ return v
+end)
+
+function lpdf.flushfonts()
+
+ local mainfonts = { }
+
+ statistics.starttiming(objects)
+
+ for fontid, used in sortedhash(lpdf.usedcharacters) do
+
+ -- for a bitmap we need a different hash unless we stick to a fixed high
+ -- resolution which makes much sense
+
+ local hash = getstreamhash(fontid)
+ if hash then
+ local parent = mainfonts[hash]
+ if not parent then
+ local fontdata = usedfonts[fontid]
+ local rawdata = fontdata.shared and fontdata.shared.rawdata
+ local resources = fontdata.resources
+ local properties = fontdata.properties -- writingmode and type3
+ local parameters = fontdata.parameters -- used in type3
+ if not rawdata then
+ -- we have a virtual font that loaded directly ... at some point i will
+ -- sort this out (in readanddefine we need to do a bit more) .. the problem
+ -- is that we have a hybrid font then
+ for xfontid, xfontdata in next, fonts.hashes.identifiers do
+ if fontid ~= xfontid then
+ local xhash = getstreamhash(xfontid)
+ if hash == xhash then
+ rawdata = xfontdata.shared and xfontdata.shared.rawdata
+ if rawdata then
+ resources = xfontdata.resources
+ properties = xfontdata.properties
+ parameters = xfontdata.parameters
+ break
+ end
+ end
+ end
+ end
+ end
+ if rawdata then
+ parent = {
+ hash = hash,
+ fontdata = fontdata,
+ filename = resources.filename or properties.filename or "unset",
+ indices = { },
+ rawdata = rawdata,
+ properties = properties, -- we assume consistency
+ parameters = parameters, -- we assume consistency
+ streams = { },
+ objectnumber = objects[hash],
+ basefontname = subsetname(properties.psname or properties.name or "unset"),
+ name = names[hash],
+ }
+ mainfonts[hash] = parent
+ noffonts = noffonts + 1
+ end
+ end
+ if parent then
+ local indices = parent.indices
+ for k in next, used do
+ indices[k] = true
+ end
+ end
+ end
+ end
+
+ for hash, details in sortedhash(mainfonts) do
+ if next(details.indices) then
+ local filename = details.filename
+ if trace_fonts then
+ report_fonts("embedding %a hashed as %a",filename,hash)
+ end
+ local properties = details.properties
+ local bitmap = properties.usedbitmap
+ if bitmap then
+ local format = "type3"
+ local writer = mainwriters[format]
+ if writer then
+ if trace_fonts then
+ report_fonts("using main writer %a",format)
+ end
+ writer(details)
+ end
+ else
+ local format = properties.format
+ local writer = mainwriters[format]
+ if not writer then
+ -- at some point we should do this in the frontend but
+ -- luatex does it anyway then
+ local encoding, pfbfile, encfile = getmapentry(filename)
+ if encoding and pfbfile then
+ filename = pfbfile
+ format = "type1"
+ --
+ -- another (temp) hack
+ local size = details.fontdata.parameters.size
+ local factor = details.fontdata.parameters.factor
+ local descriptions = { }
+ local characters = details.fontdata.characters
+ --
+ local names, _, _, metadata = fonts.constructors.handlers.pfb.loadvector(pfbfile)
+ local reverse = table.swapped(names)
+ local vector = encoding.vector
+ local indices = details.indices
+ local remapped = { }
+ local factor = number.dimenfactors.bp * size / 65536
+ for k, v in next, indices do
+ local name = vector[k]
+ local index = reverse[name] or 0
+ local width = factor * (characters[k].width or 0)
+ descriptions[k] = {
+ width = width,
+ index = index,
+ name = name,
+ }
+ remapped[index] = true
+ end
+ details.indices = remapped
+ --
+ details.rawdata.descriptions = descriptions
+ details.filename = filename
+ details.rawdata.metadata = { }
+ --
+ properties.filename = filename
+ properties.format = format
+ writer = mainwriters[format]
+ end
+ end
+ if writer then
+ if trace_fonts then
+ report_fonts("using main writer %a",format)
+ end
+ -- better move this test to the writers .. cleaner
+ local streams = loadstreamdata(details.fontdata)
+ if streams and streams.fontheader and streams.names then
+ details.streams = streams
+ writer(details)
+ details.streams = { }
+ elseif trace_fonts then
+ -- can be ok for e.g. emoji
+ report_fonts("no streams in %a",filename)
+ end
+ -- free some memory
+ else -- if trace_fonts then
+ report_fonts("no %a writer for %a",format,filename)
+ end
+ end
+ end
+ mainfonts[details.hash] = false -- done
+ end
+
+ statistics.stoptiming(objects)
+
+end
+
+statistics.register("font embedding time",function()
+ if noffonts > 0 then
+ return format("%s seconds, %s fonts", statistics.elapsedtime(objects),noffonts)
+ end
+end)
+
+updaters.register("backend.update.pdf",function()
+ fonts.constructors.addtounicode = false
+end)
+
+-- this is temporary
+
+local done = false
+
+updaters.register("backend.update.pdf",function()
+ if not done then
+ function pdf.getfontobjnum (k) return objects[k] end
+ function pdf.getfontname (k) return names [k] end
+ function pdf.includechar () end -- maybe, when we need it
+ function pdf.includefont () end -- maybe, when we need it
+ function pdf.includecharlist () end -- maybe, when we need it
+ function pdf.setomitcidset (v) includecidset = not v end
+ function pdf.setomitcharset () end -- we don't need that in lmtx
+ function pdf.setsuppressoptionalinfo() end -- we don't need that in lmtx
+ function pdf.mapfile (n) loadmapfile(n) end
+ function pdf.mapline (n) loadmapline(n) end
+ -- this will change
+ lpdf.registerdocumentfinalizer(lpdf.flushfonts,1,"wrapping up fonts")
+ done = true
+ end
+end)
diff --git a/tex/context/base/mkiv/lpdf-epa.lua b/tex/context/base/mkiv/lpdf-epa.lua
index 570d73881..01c4e237f 100644
--- a/tex/context/base/mkiv/lpdf-epa.lua
+++ b/tex/context/base/mkiv/lpdf-epa.lua
@@ -295,6 +295,12 @@ function codeinjections.mergereferences(specification)
if annotation.Subtype == "Link" then
local a = annotation.A
if not a then
+ local d = annotation.Dest
+ if d then
+ annotation.A = { S = "GoTo", D = d } -- no need for a dict
+ end
+ end
+ if not a then
report_link("missing link annotation")
else
local x, y, w, h = getdimensions(annotation,llx,lly,xscale,yscale,width,height,report_link)
diff --git a/tex/context/base/mkiv/lpdf-img.lua b/tex/context/base/mkiv/lpdf-img.lua
new file mode 100644
index 000000000..aa91f9f22
--- /dev/null
+++ b/tex/context/base/mkiv/lpdf-img.lua
@@ -0,0 +1,1206 @@
+if not modules then modules = { } end modules ['lpdf-img'] = {
+ version = 1.001,
+ comment = "companion to lpdf-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This started as an experiment but has potential for some (cached) optimizations.
+-- At some point we can also use it for fonts. For small images performance is ok
+-- with pure lua but for bigger images we can use some helpers. Normally in a
+-- typesetting workflow non-interlaced images are used. One should convert
+-- interlaced images to more efficient non-interlaced ones (ok, we can cache
+-- them if needed).
+--
+-- The \LUA\ code is slightly optimized so we could have done with less lines if
+-- we wanted but best gain a little. The idea is that we collect striped (in stages)
+-- so that we can play with substitutions.
+
+local type = type
+local concat, move = table.concat, table.move
+local ceil = math.ceil
+local char, find = string.char, string.find
+local idiv = number.idiv
+local band, rshift = bit32.band, bit32.rshift
+
+local loaddata = io.loaddata
+local setmetatableindex = table.setmetatableindex
+
+local streams = utilities.streams
+local openstring = streams.openstring
+local readstring = streams.readstring
+local readbytetable = streams.readbytetable
+
+local tobytetable = string.bytetable
+
+local lpdf = lpdf or { }
+local pdfdictionary = lpdf.dictionary
+local pdfarray = lpdf.array
+local pdfconstant = lpdf.constant
+local pdfstring = lpdf.string
+local pdfflushstreamobject = lpdf.flushstreamobject
+local pdfreference = lpdf.reference
+
+local pdfmajorversion = lpdf.majorversion
+local pdfminorversion = lpdf.minorversion
+
+local createimage = images.create
+
+local zlibcompress = flate and flate.zip_compress or zlib.compress
+local zlibdecompress = zlib.decompress -- todo
+
+local trace = false
+
+local report_jpg = logs.reporter("graphics","jpg")
+local report_jp2 = logs.reporter("graphics","jp2")
+local report_png = logs.reporter("graphics","png")
+
+trackers.register("graphics.backend", function(v) trace = v end)
+
+local injectors = { }
+lpdf.injectors = injectors
+
+local chars = setmetatableindex(function(t,k) -- share this one
+ local v = (k <= 0 and "\000") or (k >= 255 and "\255") or char(k)
+ t[k] = v
+ return v
+end)
+
+do
+
+ function injectors.jpg(specification)
+ if specification.error then
+ return
+ end
+ local filename = specification.filename
+ if not filename then
+ return
+ end
+ local colorspace = specification.colorspace or jpg_gray
+ local decodearray = nil
+ ----- procset = colorspace == 0 and "image b" or "image c"
+ if colorspace == 1 then
+ colorspace = "DeviceGray"
+ elseif colorspace == 2 then
+ colorspace = "DeviceRGB"
+ elseif colorspace == 3 then
+ colorspace = "DeviceCMYK"
+ decodearray = pdfarray { 1, 0, 1, 0, 1, 0, 1, 0 }
+ end
+ -- todo: set filename
+ local xsize = specification.xsize
+ local ysize = specification.ysize
+ local colordepth = specification.colordepth
+ local content = loaddata(filename)
+ local xobject = pdfdictionary {
+ Type = pdfconstant("XObject"),
+ Subtype = pdfconstant("Image"),
+ -- BBox = pdfarray { 0, 0, xsize, ysize },
+ Width = xsize,
+ Height = ysize,
+ BitsPerComponent = colordepth,
+ Filter = pdfconstant("DCTDecode"),
+ ColorSpace = pdfconstant(colorspace),
+ Decode = decodearray,
+ Length = #content, -- specification.length
+ } + specification.attr
+ if trace then
+ report_jpg("%s: width %i, height %i, colordepth %i, size %i",filename,xsize,ysize,colordepth,#content)
+ end
+ return createimage {
+ bbox = { 0, 0, specification.width/xsize, specification.height/ysize }, -- mandate
+ transform = specification.transform,
+ nolength = true,
+ nobbox = true,
+ notype = true,
+ stream = content,
+ attr = xobject(),
+ }
+ end
+
+end
+
+do
+
+ function injectors.jp2(specification)
+ if specification.error then
+ return
+ end
+ local filename = specification.filename
+ if not filename then
+ return
+ end
+ -- todo: set filename
+ local xsize = specification.xsize
+ local ysize = specification.ysize
+ local content = loaddata(filename)
+ local xobject = pdfdictionary {
+ Type = pdfconstant("XObject"),
+ Subtype = pdfconstant("Image"),
+ BBox = pdfarray { 0, 0, xsize, ysize },
+ Width = xsize,
+ Height = ysize,
+ Filter = pdfconstant("JPXDecode"),
+ Length = #content, -- specification.length
+ } + specification.attr
+ if trace then
+ report_jp2("%s: width %i, height %i, size %i",filename,xsize,ysize,#content)
+ end
+ return createimage {
+ bbox = { 0, 0, specification.width/xsize, specification.height/ysize }, -- mandate
+ transform = specification.transform,
+ nolength = true,
+ nobbox = true,
+ notype = true,
+ stream = content,
+ attr = xobject(),
+ }
+ end
+
+end
+
+do
+
+ -- We don't like interlaced files. You can deinterlace them beforehand because otherwise
+ -- each run you add runtime. Actually, even masked images can best be converted to PDF
+ -- beforehand.
+
+ -- The amount of code is larger that I like and looks somewhat redundant but we sort of
+ -- optimize a few combinations that happen often.
+
+ local pngapplyfilter = pnge and pnge.applyfilter
+ local pngsplitmask = pnge and pnge.splitmask
+ local pnginterlace = pnge and pnge.interlace
+ local pngexpand = pnge and pnge.expand
+
+ local filtermask, decodemask, decodestrip, transpose, expand
+
+ local newindex = lua.newindex
+ local newtable = lua.newtable
+
+ local function newoutput(size)
+ if newindex then
+ return newindex(size,0)
+ end
+ local t = newtable and newtable(size,0) or { }
+ for i=1,size do
+ t[i] = 0
+ end
+ return t
+ end
+
+ local function convert(t)
+ if type(t) == "table" then
+ for i=1,#t do
+ local ti = t[i]
+ if ti ~= "" then -- soon gone
+ t[i] = chars[ti]
+ end
+ end
+ return concat(t)
+ else
+ return t
+ end
+ end
+
+ local function zero(t,k)
+ return 0
+ end
+
+ local function applyfilter(t,xsize,ysize,bpp)
+ local len = xsize * bpp + 1
+ local n = 1
+ local m = len - 1
+ for i=1,ysize do
+ local filter = t[n]
+ t[n] = ""
+ if filter == 0 then
+ elseif filter == 1 then
+ for j=n+bpp+1,n+m do
+ t[j] = (t[j] + t[j-bpp]) % 256
+ end
+ elseif filter == 2 then
+ for j=n+1,n+m do
+ t[j] = (t[j] + t[j-len]) % 256
+ end
+ elseif filter == 3 then
+ for j=n+1,n+bpp do
+ t[j] = (t[j] + idiv(t[j-len],2)) % 256
+ end
+ for j=n+bpp+1,n+m do
+ t[j] = (t[j] + idiv(t[j-bpp] + t[j-len],2)) % 256
+ end
+ elseif filter == 4 then
+ for j=n+1,n+bpp do
+ local p = j - len
+ local b = t[p]
+ if b > 0 then
+ t[j] = (t[j] + b) % 256
+ end
+ end
+ for j=n+bpp+1,n+m do
+ local p = j - len
+ local a = t[j-bpp]
+ local b = t[p]
+ local c = t[p-bpp]
+ local pa = b - c
+ local pb = a - c
+ local pc = pa + pb
+ if pa < 0 then pa = - pa end
+ if pb < 0 then pb = - pb end
+ if pc < 0 then pc = - pc end
+ t[j] = (t[j] + ((pa <= pb and pa <= pc and a) or (pb <= pc and b) or c)) % 256
+ end
+ end
+ n = n + len
+ end
+ return t
+ end
+
+ local filtermask_l = function (content,xsize,ysize,colordepth,colorspace,hasfilter)
+ local mask = { }
+ local bytes = colordepth == 16 and 2 or 1
+ local bpp = colorspace == "DeviceRGB" and 3 or 1
+ local length = #content
+ local size = ysize * xsize * ((bpp+1)*bytes + (hasfilter and 1 or 0))
+ local n = 1
+ local l = 1
+ if bytes == 2 then
+ if bpp == 1 then
+ for i=1,ysize do
+ if hasfilter then
+ content[n] = "" ; n = n + 1
+ end
+ for j=1,xsize do
+ content[n] = chars[content[n]] ; n = n + 1
+ content[n] = chars[content[n]] ; n = n + 1
+ mask[l] = chars[content[n]] ; l = l + 1
+ content[n] = "" ; n = n + 1
+ mask[l] = chars[content[n]] ; l = l + 1
+ content[n] = "" ; n = n + 1
+ end
+ end
+ elseif bpp == 3 then
+ for i=1,ysize do
+ if hasfilter then
+ content[n] = "" ; n = n + 1
+ end
+ for j=1,xsize do
+ content[n] = chars[content[n]] ; n = n + 1
+ content[n] = chars[content[n]] ; n = n + 1
+ content[n] = chars[content[n]] ; n = n + 1
+ content[n] = chars[content[n]] ; n = n + 1
+ content[n] = chars[content[n]] ; n = n + 1
+ content[n] = chars[content[n]] ; n = n + 1
+ mask[l] = chars[content[n]] ; l = l + 1
+ content[n] = "" ; n = n + 1
+ mask[l] = chars[content[n]] ; l = l + 1
+ content[n] = "" ; n = n + 1
+ end
+ end
+ else
+ return "", ""
+ end
+ else
+ if bpp == 1 then
+ for i=1,ysize do
+ if hasfilter then
+ content[n] = "" ; n = n + 1
+ end
+ for j=1,xsize do
+ content[n] = chars[content[n]] ; n = n + 1
+ mask[l] = chars[content[n]] ; l = l + 1
+ content[n] = "" ; n = n + 1
+ end
+ end
+ elseif bpp == 3 then
+ for i=1,ysize do
+ if hasfilter then
+ content[n] = "" ; n = n + 1
+ end
+ for j=1,xsize do
+ content[n] = chars[content[n]] ; n = n + 1
+ content[n] = chars[content[n]] ; n = n + 1
+ content[n] = chars[content[n]] ; n = n + 1
+ mask[l] = chars[content[n]] ; l = l + 1
+ content[n] = "" ; n = n + 1
+ end
+ end
+ else
+ return "", ""
+ end
+ end
+ return concat(content), concat(mask)
+ end
+
+ local decodemask_l = function(content,xsize,ysize,colordepth,colorspace)
+ local bytes = colordepth == 16 and 2 or 1
+ local bpp = colorspace == "DeviceRGB" and 3 or 1
+ local slice = bytes*(bpp+1)
+ local length = #content
+ local size = ysize * xsize * ((bpp+1)*bytes + 1) -- assume filter
+ content = openstring(content)
+ content = readbytetable(content,length)
+ setmetatableindex(content,zero)
+ applyfilter(content,xsize,ysize,slice)
+ content, mask = filtermask(content,xsize,ysize,colordepth,colorspace,true)
+ return content, mask
+ end
+
+ local filtermask_c = function(content,xsize,ysize,colordepth,colorspace)
+ local bytes = colordepth == 16 and 2 or 1
+ local bpp = colorspace == "DeviceRGB" and 3 or 1
+ return pngsplitmask(content,xsize,ysize,bpp,bytes)
+ end
+
+ local decodemask_c = function(content,xsize,ysize,colordepth,colorspace)
+ local mask = true
+ local filter = false
+ local bytes = colordepth == 16 and 2 or 1
+ local bpp = colorspace == "DeviceRGB" and 3 or 1
+ local slice = bytes * (bpp + 1) -- always a mask
+ content = pngapplyfilter(content,xsize,ysize,slice)
+ return pngsplitmask(content,xsize,ysize,bpp,bytes,mask,filter)
+ end
+
+ local function decodestrip_l(s,nx,ny,slice)
+ local input = readbytetable(s,ny*(nx*slice+1))
+ setmetatableindex(input,zero)
+ applyfilter(input,nx,ny,slice)
+ return input, true
+ end
+
+ local function decodestrip_c(s,nx,ny,slice)
+ local input = readstring(s,ny*(nx*slice+1))
+ input = pngapplyfilter(input,nx,ny,slice)
+ return input, false
+ end
+
+ local xstart = { 0, 4, 0, 2, 0, 1, 0 }
+ local ystart = { 0, 0, 4, 0, 2, 0, 1 }
+ local xstep = { 8, 8, 4, 4, 2, 2, 1 }
+ local ystep = { 8, 8, 8, 4, 4, 2, 2 }
+
+ local xblock = { 8, 4, 4, 2, 2, 1, 1 }
+ local yblock = { 8, 8, 4, 4, 2, 2, 1 }
+
+ local function transpose_l(xsize,ysize,slice,pass,input,output,filter)
+ local xstart = xstart[pass]
+ local xstep = xstep[pass]
+ local ystart = ystart[pass]
+ local ystep = ystep[pass]
+ local nx = idiv(xsize + xstep - xstart - 1,xstep)
+ local ny = idiv(ysize + ystep - ystart - 1,ystep)
+ local offset = filter and 1 or 0
+ local xstep = xstep * slice
+ local xstart = xstart * slice
+ local xsize = xsize * slice
+ local target = ystart * xsize + xstart + 1
+ local ystep = ystep * xsize
+ local start = 1
+ local plus = nx * xstep
+ local step = plus - xstep
+ if not output then
+ output = newoutput(xsize*(parts or slice)*ysize)
+ end
+ if slice == 1 then
+ for j=0,ny-1 do
+ start = start + offset
+ local target = target + j * ystep
+ for target=target,target+step,xstep do
+ output[target] = input[start]
+ start = start + slice
+ end
+ end
+ elseif slice == 2 then
+ for j=0,ny-1 do
+ start = start + offset
+ local target = target + j * ystep
+ for target=target,target+step,xstep do
+ output[target] = input[start]
+ output[target+1] = input[start+1]
+ start = start + slice
+ end
+ end
+ elseif slice == 3 then
+ for j=0,ny-1 do
+ start = start + offset
+ local target = target + j * ystep
+ for target=target,target+step,xstep do
+ output[target] = input[start]
+ output[target+1] = input[start+1]
+ output[target+2] = input[start+2]
+ start = start + slice
+ end
+ end
+ elseif slice == 4 then
+ for j=0,ny-1 do
+ start = start + offset
+ local target = target + j * ystep
+ for target=target,target+step,xstep do
+ output[target] = input[start]
+ output[target+1] = input[start+1]
+ output[target+2] = input[start+2]
+ output[target+3] = input[start+3]
+ start = start + slice
+ end
+ end
+ else
+ local delta = slice - 1
+ for j=0,ny-1 do
+ start = start + offset
+ local target = target + j * ystep
+ for target=target,target+step,xstep do
+ move(input,start,start+delta,target,output)
+ start = start + slice
+ end
+ end
+ end
+ return output;
+ end
+
+ local transpose_c = pnginterlace
+
+ -- print(band(rshift(v,4),0x03),extract(v,4,2))
+ -- print(band(rshift(v,6),0x03),extract(v,6,2))
+
+ local function expand_l(t,xsize,ysize,parts,run,factor,filter)
+ local size = ysize * xsize + 1 -- a bit of overshoot, needs testing, probably a few bytes us ok
+ local xline = filter and (run+1) or run
+ local f = filter and 1 or 0
+ local l = xline - 1
+ local n = 1
+ local o = newoutput(size)
+ local k = 0
+ if factor then
+ if parts == 4 then
+ for i=1,ysize do
+ for j=n+f,n+l do
+ local v = t[j]
+ if v == 0 then
+ k = k + 2
+ else
+ k = k + 1 ; o[k] = extract4(v,4) * 0x11
+ k = k + 1 ; o[k] = extract4(v,0) * 0x11
+ end
+ end
+ k = i * xsize
+ n = n + xline
+ end
+ elseif parts == 2 then
+ for i=1,ysize do
+ for j=n+f,n+l do
+ local v = t[j]
+ if v == 0 then
+ k = k + 4
+ else
+ k = k + 1 ; o[k] = extract2(v,6) * 0x55
+ k = k + 1 ; o[k] = extract2(v,4) * 0x55
+ k = k + 1 ; o[k] = extract2(v,2) * 0x55
+ k = k + 1 ; o[k] = extract2(v,0) * 0x55
+ end
+ end
+ k = i * xsize
+ n = n + xline
+ end
+ else
+ for i=1,ysize do
+ for j=n+f,n+l do
+ local v = t[j]
+ if v == 0 then
+ k = k + 8
+ else
+ k = k + 1 ; if band(v,0x80) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,7) * 0xFF
+ k = k + 1 ; if band(v,0x40) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,6) * 0xFF
+ k = k + 1 ; if band(v,0x20) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,5) * 0xFF
+ k = k + 1 ; if band(v,0x10) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,4) * 0xFF
+ k = k + 1 ; if band(v,0x08) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,3) * 0xFF
+ k = k + 1 ; if band(v,0x04) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,2) * 0xFF
+ k = k + 1 ; if band(v,0x02) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,1) * 0xFF
+ k = k + 1 ; if band(v,0x01) ~= 0 then o[k] = 0xFF end -- o[k] = extract1(v,0) * 0xFF
+ end
+ end
+ k = i * xsize
+ n = n + xline
+ end
+ end
+ else
+ if parts == 4 then
+ for i=1,ysize do
+ for j=n+f,n+l do
+ local v = t[j]
+ if v == 0 then
+ k = k + 2
+ else
+ k = k + 1 ; o[k] = extract4(v,4)
+ k = k + 1 ; o[k] = extract4(v,0)
+ end
+ end
+ k = i * xsize
+ n = n + xline
+ end
+ elseif parts == 2 then
+ for i=1,ysize do
+ for j=n+f,n+l do
+ local v = t[j]
+ if v == 0 then
+ k = k + 4
+ else
+ k = k + 1 ; o[k] = extract2(v,6)
+ k = k + 1 ; o[k] = extract2(v,4)
+ k = k + 1 ; o[k] = extract2(v,2)
+ k = k + 1 ; o[k] = extract2(v,0)
+ end
+ end
+ k = i * xsize
+ n = n + xline
+ end
+ else
+ for i=1,ysize do
+ for j=n+f,n+l do
+ local v = t[j]
+ if v == 0 then
+ k = k + 8
+ else
+ k = k + 1 ; if band(v,0x80) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,7)
+ k = k + 1 ; if band(v,0x40) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,6)
+ k = k + 1 ; if band(v,0x20) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,5)
+ k = k + 1 ; if band(v,0x10) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,4)
+ k = k + 1 ; if band(v,0x08) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,3)
+ k = k + 1 ; if band(v,0x04) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,2)
+ k = k + 1 ; if band(v,0x02) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,1)
+ k = k + 1 ; if band(v,0x01) ~= 0 then o[k] = 1 end -- o[k] = extract1(v,0)
+ end
+ end
+ k = i * xsize
+ n = n + xline
+ end
+ end
+ end
+ for i=size,xsize * ysize +1,-1 do
+ o[i] = nil
+ end
+ return o, false
+ end
+
+ local expand_c = pngexpand
+
+ local function analyze(colordepth,colorspace,palette,mask)
+ -- return bytes, parts, factor
+ if palette then
+ if colordepth == 16 then
+ return 2, false, false
+ elseif colordepth == 8 then
+ return 1, false, false
+ elseif colordepth == 4 then
+ return 1, 4, false
+ elseif colordepth == 2 then
+ return 1, 2, false
+ elseif colordepth == 1 then
+ return 1, 1, false
+ end
+ elseif colorspace == "DeviceGray" then
+ if colordepth == 16 then
+ return mask and 4 or 2, false, false
+ elseif colordepth == 8 then
+ return mask and 2 or 1, false, false
+ elseif colordepth == 4 then
+ return 1, 4, true
+ elseif colordepth == 2 then
+ return 1, 2, true
+ elseif colordepth == 1 then
+ return 1, 1, true
+ end
+ else
+ if colordepth == 16 then
+ return mask and 8 or 6, false, false
+ elseif colordepth == 8 then
+ return mask and 4 or 3, false, false
+ elseif colordepth == 4 then
+ return 3, 4, true
+ elseif colordepth == 2 then
+ return 3, 2, true
+ elseif colordepth == 1 then
+ return 3, 1, true
+ end
+ end
+ return false, false, false
+ end
+
+ -- 1 6 4 6 2 6 4 6
+ -- 7 7 7 7 7 7 7 7
+ -- 5 6 5 6 5 6 5 6
+ -- 7 7 7 7 7 7 7 7
+ -- 3 6 4 6 3 6 4 6
+ -- 7 7 7 7 7 7 7 7
+ -- 5 6 5 6 5 6 5 6
+ -- 7 7 7 7 7 7 7 7
+
+ local function deinterlace(content,xsize,ysize,colordepth,colorspace,palette,mask)
+ local slice, parts, factor = analyze(colordepth,colorspace,palette,mask)
+ if slice then
+ content = openstring(zlibdecompress(content))
+ local filter = false
+ local output = false
+ for pass=1,7 do
+ local xstart = xstart[pass]
+ local xstep = xstep[pass]
+ local ystart = ystart[pass]
+ local ystep = ystep[pass]
+ local nx = idiv(xsize + xstep - xstart - 1,xstep)
+ local ny = idiv(ysize + ystep - ystart - 1,ystep)
+ if nx > 0 and ny > 0 then
+ local input, filter
+ if parts then
+ local nxx = ceil(nx*parts/8)
+ input, filter = decodestrip(content,nxx,ny,slice)
+ input, filter = expand(input,nx,ny,parts,nxx,factor,filter)
+ else
+ input, filter = decodestrip(content,nx,ny,slice)
+ end
+ output = transpose(xsize,ysize,slice,pass,input,output,filter)
+ end
+ -- if pass == 3 then
+ -- break -- still looks ok, could be nice for a preroll
+ -- end
+ end
+ return output, parts and 8 or false
+ end
+ end
+
+ -- 1 (palette used), 2 (color used), and 4 (alpha channel used)
+
+ -- paeth:
+ --
+ -- p = a + b - c
+ -- pa = abs(p - a) => a + b - c - a => b - c
+ -- pb = abs(p - b) => a + b - c - b => a - c
+ -- pc = abs(p - c) => a + b - c - c => a + b - c - c => a - c + b - c => pa + pb
+
+ local function full(t,k) local v = "\xFF" t[k] = v return v end
+
+ local function expandvector(transparent)
+ local s = openstring(transparent)
+ local n = #transparent
+ local r = { }
+ for i=0,n-1 do
+ r[i] = readstring(s,1) -- readchar
+ end
+ setmetatableindex(r,full)
+ return r
+ end
+
+ local function createmask_l(content,palette,transparent,xsize,ysize,colordepth,colorspace)
+ if palette then
+ local r = expandvector(transparent)
+ local size = xsize*ysize
+ local len = ceil(xsize*colordepth/8) + 1
+ local o = newoutput(xsize*ysize)
+ local u = setmetatableindex(zero)
+ content = zlibdecompress(content)
+ content = openstring(content)
+ for i=0,ysize-1 do
+ local t = readbytetable(content,len)
+ local k = i * xsize
+ local filter = t[1]
+ if filter == 0 then
+ elseif filter == 1 then
+ for j=3,len do
+ t[j] = (t[j] + t[j-1]) % 256
+ end
+ elseif filter == 2 then
+ for j=2,len do
+ t[j] = (t[j] + u[j]) % 256
+ end
+ elseif filter == 3 then
+ local j = 2
+ t[j] = (t[j] + idiv(u[j],2)) % 256
+ for j=3,len do
+ t[j] = (t[j] + idiv(t[j-1] + u[j],2)) % 256
+ end
+ elseif filter == 4 then
+ local j = 2
+ local p = j - len
+ local b = t[p]
+ if b < 0 then
+ b = - b
+ end
+ if b > 0 then
+ t[j] = (t[j] + b) % 256
+ end
+ for j=3,len do
+ local p = j - len
+ local a = t[j-1]
+ local b = t[p]
+ local c = t[p-1]
+ local pa = b - c
+ local pb = a - c
+ local pc = pa + pb
+ if pa < 0 then pa = - pa end
+ if pb < 0 then pb = - pb end
+ if pc < 0 then pc = - pc end
+ t[j] = (t[j] + ((pa <= pb and pa <= pc and a) or (pb <= pc and b) or c)) % 256
+ end
+ end
+ if colordepth == 8 then
+ for j=2,len do
+ local v = t[j]
+ k = k + 1 ; o[k] = r[v]
+ end
+ elseif colordepth == 4 then
+ for j=2,len do
+ local v = t[j]
+ k = k + 1 ; o[k] = r[extract4(v,4)]
+ k = k + 1 ; o[k] = r[extract4(v,0)]
+ end
+ elseif colordepth == 2 then
+ for j=2,len do
+ local v = t[j]
+ k = k + 1 ; o[k] = r[extract2(v,6)]
+ k = k + 1 ; o[k] = r[extract2(v,4)]
+ k = k + 1 ; o[k] = r[extract2(v,2)]
+ k = k + 1 ; o[k] = r[extract2(v,0)]
+ end
+ else
+ for j=2,len do
+ local v = t[j]
+ k = k + 1 ; o[k] = r[extract1(v,7)]
+ k = k + 1 ; o[k] = r[extract1(v,6)]
+ k = k + 1 ; o[k] = r[extract1(v,5)]
+ k = k + 1 ; o[k] = r[extract1(v,4)]
+ k = k + 1 ; o[k] = r[extract1(v,3)]
+ k = k + 1 ; o[k] = r[extract1(v,2)]
+ k = k + 1 ; o[k] = r[extract1(v,1)]
+ k = k + 1 ; o[k] = r[extract1(v,0)]
+ end
+ end
+ u = t
+ end
+ return concat(o,"",1,size)
+ end
+ end
+
+ local function createmask_c(content,palette,transparent,xsize,ysize,colordepth,colorspace)
+ if palette then
+ local r = expandvector(transparent)
+ local size = xsize*ysize
+ local len = ceil(xsize*colordepth/8)
+ local o = newoutput(size)
+ content = zlibdecompress(content)
+ content = pngapplyfilter(content,len,ysize,1) -- nostrip (saves copy)
+ content = openstring(content)
+ for i=0,ysize-1 do
+ local t = readbytetable(content,len)
+ local k = i * xsize
+ if colordepth == 8 then
+ for j=1,len do
+ local v = t[j]
+ k = k + 1 ; o[k] = r[v]
+ end
+ elseif colordepth == 4 then
+ for j=1,len do
+ local v = t[j]
+ k = k + 1 ; o[k] = r[extract4(v,4)]
+ k = k + 1 ; o[k] = r[extract4(v,0)]
+ end
+ elseif colordepth == 2 then
+ for j=1,len do
+ local v = t[j]
+ k = k + 1 ; o[k] = r[extract2(v,6)]
+ k = k + 1 ; o[k] = r[extract2(v,4)]
+ k = k + 1 ; o[k] = r[extract2(v,2)]
+ k = k + 1 ; o[k] = r[extract2(v,0)]
+ end
+ else
+ for j=1,len do
+ local v = t[j]
+ k = k + 1 ; o[k] = r[extract1(v,7)]
+ k = k + 1 ; o[k] = r[extract1(v,6)]
+ k = k + 1 ; o[k] = r[extract1(v,5)]
+ k = k + 1 ; o[k] = r[extract1(v,4)]
+ k = k + 1 ; o[k] = r[extract1(v,3)]
+ k = k + 1 ; o[k] = r[extract1(v,2)]
+ k = k + 1 ; o[k] = r[extract1(v,1)]
+ k = k + 1 ; o[k] = r[extract1(v,0)]
+ end
+ end
+ end
+ return concat(o,"",1,size)
+ end
+ end
+
+ local function switch(v)
+ if v then
+ filtermask = filtermask_l
+ decodemask = decodemask_l
+ decodestrip = decodestrip_l
+ transpose = transpose_l
+ expand = expand_l
+ createmask = createmask_l
+ else
+ filtermask = filtermask_c
+ decodemask = decodemask_c
+ decodestrip = decodestrip_c
+ transpose = transpose_c
+ expand = expand_c
+ createmask = createmask_c
+ end
+ end
+
+ if pngapplyfilter then
+ switch(false)
+ directives.register("graphics.png.purelua",switch)
+ else
+ switch(true)
+ end
+
+ local alwaysdecode = false
+
+ -- directives.register("graphics.png.decode", function(v)
+ -- alwaysdecode = v
+ -- end)
+
+ function injectors.png(specification)
+-- inspect(specification)
+ if specification.error then
+ return
+ end
+ local filename = specification.filename
+ if not filename then
+ return
+ end
+ local colorspace = specification.colorspace
+ if not colorspace then
+ return
+ end
+ local interlace = specification.interlace or 0
+ if interlace == 1 then
+ interlace = true
+ elseif interlace == 0 then
+ interlace = false
+ else
+ report_png("unknown interlacing %i",interlace)
+ return
+ end
+ local tables = specification.tables
+ if not tables then
+ return
+ end
+ local idat = tables.idat
+ if not idat then
+ return
+ end
+ local pngfile = io.open(filename,"rb") -- todo: in-mem too
+ if not pngfile then
+ return
+ end
+ local content = idat(pngfile,true)
+ tables.idat = false
+ --
+ -- if tables.gama then
+ -- report_png("ignoring gamma correction")
+ -- end
+ --
+ local xsize = specification.xsize
+ local ysize = specification.ysize
+ local colordepth = specification.colordepth or 8
+ local mask = false
+ local transparent = false
+ local palette = false
+ local colors = 1
+ if colorspace == 0 then -- gray | image b
+ colorspace = "DeviceGray"
+ transparent = true
+ elseif colorspace == 2 then -- rgb | image c
+ colorspace = "DeviceRGB"
+ colors = 3
+ transparent = true
+ elseif colorspace == 3 then -- palette | image c+i
+ colorspace = "DeviceRGB"
+ palette = true
+ transparent = true
+ elseif colorspace == 4 then -- gray | alpha | image b
+ colorspace = "DeviceGray"
+ mask = true
+ elseif colorspace == 6 then -- rgb | alpha | image c
+ colorspace = "DeviceRGB"
+ colors = 3
+ mask = true
+ else
+ report_png("unknown colorspace %i",colorspace)
+ return
+ end
+ --
+ if transparent then
+ local trns = tables.trns
+ if trns then
+ transparent = trns(pngfile,true)
+ if transparent == "" then
+ transparent = false
+ end
+ tables.trns = false
+ else
+ transparent = false
+ end
+ end
+ --
+ local decode = alwaysdecode
+ local major = pdfmajorversion()
+ local minor = pdfminorversion()
+ if major > 1 then
+ -- we're okay
+ elseif minor < 5 and colordepth == 16 then
+ report_png("16 bit colordepth not supported in pdf < 1.5")
+ return
+ elseif minor < 4 and (mask or transparent) then
+ report_png("alpha channels not supported in pdf < 1.4")
+ return
+ elseif minor < 2 then
+ report_png("you'd better use a version > 1.2")
+ return
+ -- decode = true
+ end
+ --
+ -- todo: compresslevel (or delegate)
+ --
+ if palette then
+ local plte = tables.plte
+ if plte then
+ palette = plte(pngfile,true)
+ if palette == "" then
+ palette = false
+ end
+ tables.plte = false
+ else
+ palette = false
+ end
+ end
+ --
+ if interlace then
+ local r, p = deinterlace(content,xsize,ysize,colordepth,colorspace,palette,mask)
+ if not r then
+ return
+ end
+ if p then
+ colordepth = p
+ end
+ if mask then
+ if not (colordepth == 8 or colordepth == 16) then
+ report_png("mask can't be split from the image")
+ return
+ end -- get rid of bpp:
+ content, mask = filtermask(r,xsize,ysize,colordepth,colorspace,false)
+ else
+ content = convert(r) -- can be in deinterlace if needed
+ end
+ content = zlibcompress(content,3)
+ decode = true
+ elseif mask then
+ if not (colordepth == 8 or colordepth == 16) then
+ report_png("mask can't be split from the image")
+ return
+ end
+ content = zlibdecompress(content)
+ content, mask = decodemask(content,xsize,ysize,colordepth,colorspace)
+ content = zlibcompress(content,3)
+ decode = true -- we don't copy the filter byte
+ elseif transparent then
+ -- in test suite
+ if palette then
+ mask = createmask(content,palette,transparent,xsize,ysize,colordepth,colorspace)
+ else
+ pallette = false
+ end
+ elseif decode then
+ -- this one needs checking
+ local bytes = analyze(colordepth,colorspace)
+ if bytes then
+ content = zlibdecompress(content)
+ content = applyfilter(content,xsize,ysize,bytes)
+ content = zlibcompress(content,3)
+ else
+ return
+ end
+ else
+ -- print("PASS ON")
+ end
+ if palette then
+ palette = pdfarray {
+ pdfconstant("Indexed"),
+ pdfconstant("DeviceRGB"),
+ idiv(#palette,3),
+ pdfreference(pdfflushstreamobject(palette)),
+ }
+ end
+ pngfile:close()
+ local xobject = pdfdictionary {
+ Type = pdfconstant("XObject"),
+ Subtype = pdfconstant("Image"),
+ -- BBox = pdfarray { 0, 0, xsize, ysize },
+ Width = xsize,
+ Height = ysize,
+ BitsPerComponent = colordepth,
+ Filter = pdfconstant("FlateDecode"),
+ ColorSpace = palette or pdfconstant(colorspace),
+ Length = #content,
+ } + specification.attr
+ if mask then
+ local d = pdfdictionary {
+ Type = pdfconstant("XObject"),
+ Subtype = pdfconstant("Image"),
+ Width = xsize,
+ Height = ysize,
+ BitsPerComponent = palette and 8 or colordepth,
+ ColorSpace = pdfconstant("DeviceGray"),
+ }
+ xobject.SMask = pdfreference(pdfflushstreamobject(mask,d()))
+ end
+ if not decode then
+ xobject.DecodeParms = pdfdictionary {
+ Colors = colors,
+ Columns = xsize,
+ BitsPerComponent = colordepth,
+ Predictor = 15,
+ }
+ end
+ if trace then
+ report_png("%s: width %i, height %i, colordepth: %i, size: %i, palette %l, mask: %l, transparent %l, decode %l",filename,xsize,ysize,colordepth,#content,palette,mask,transparent,decode)
+ end
+ if specification.colorref then
+ xobject.ColorSpace = pdfreference(specification.colorref)
+ end
+ return createimage {
+ bbox = { 0, 0, specification.width/xsize, specification.height/ysize }, -- mandate
+ transform = specification.transform,
+ nolength = true,
+ nobbox = true,
+ notype = true,
+ stream = content,
+ attr = xobject(),
+ }
+ end
+
+end
+
+do
+
+ local function pack(specification,what)
+ local t = { }
+ local n = 0
+ local s = specification.colorspace
+ local d = specification.data
+ local x = specification.xsize
+ local y = specification.ysize
+ if what == "mask" then
+ d = specification.mask
+ s = 1
+ end
+ if s == 1 then
+ for i=1,y do
+ local r = d[i]
+ for j=1,x do
+ n = n + 1 ; t[n] = chars[r[j]]
+ end
+ end
+ elseif s == 2 then
+ for i=1,y do
+ local r = d[i]
+ for j=1,x do
+ local c = r[j]
+ n = n + 1 ; t[n] = chars[c[1]]
+ n = n + 1 ; t[n] = chars[c[2]]
+ n = n + 1 ; t[n] = chars[c[3]]
+ end
+ end
+ elseif s == 3 then
+ for i=1,y do
+ local r = d[i]
+ for j=1,x do
+ local c = r[j]
+ n = n + 1 ; t[n] = chars[c[1]]
+ n = n + 1 ; t[n] = chars[c[2]]
+ n = n + 1 ; t[n] = chars[c[3]]
+ n = n + 1 ; t[n] = chars[c[4]]
+ end
+ end
+ end
+ return concat(t)
+ end
+
+ function injectors.bitmap(specification)
+ local data = specification.data
+ if not data then
+ return
+ end
+ local xsize = specification.xsize or 0
+ local ysize = specification.ysize or 0
+ if xsize == 0 or ysize == 0 then
+ return
+ end
+ local colorspace = specification.colorspace or 1
+ if colorspace == 1 then
+ colorspace = "DeviceGray"
+ elseif colorspace == 2 then
+ colorspace = "DeviceRGB"
+ elseif colorspace == 3 then
+ colorspace = "DeviceCMYK"
+ end
+ local colordepth = (specification.colordepth or 2) == 16 or 8
+ local content = pack(specification,"data")
+ local mask = specification.mask
+ local xobject = pdfdictionary {
+ Type = pdfconstant("XObject"),
+ Subtype = pdfconstant("Image"),
+ BBox = pdfarray { 0, 0, xsize, ysize },
+ Width = xsize,
+ Height = ysize,
+ BitsPerComponent = colordepth,
+ ColorSpace = pdfconstant(colorspace),
+ Length = #content, -- specification.length
+ }
+ if mask then
+ local d = pdfdictionary {
+ Type = pdfconstant("XObject"),
+ Subtype = pdfconstant("Image"),
+ Width = xsize,
+ Height = ysize,
+ BitsPerComponent = colordepth,
+ ColorSpace = pdfconstant("DeviceGray"),
+ }
+ xobject.SMask = pdfreference(pdfflushstreamobject(pack(specification,"mask"),d()))
+ end
+ return createimage {
+ bbox = { 0, 0, specification.width/xsize, specification.height/ysize }, -- mandate
+ -- nolength = true,
+ nobbox = true,
+ notype = true,
+ stream = content,
+ attr = xobject(),
+ }
+ end
+
+end
+
+-- local function validcompression(data)
+-- local d = utilities.streams.openstring(data)
+-- local b1 = utilities.streams.readbyte(d)
+-- local b2 = utilities.streams.readbyte(d)
+-- print(b1,b2)
+-- if (b1 * 256 + b2) % 31 ~= 0 then
+-- return false, "no zlib compressed file"
+-- end
+-- local method = band(b1,15)
+-- if method ~= 8 then
+-- return false, "method 8 expected"
+-- end
+-- local detail = band(rshift(b1,4),15)
+-- if detail > 7 then
+-- return false, "window 32 expected"
+-- end
+-- local preset = band(rshift(b2,5),1)
+-- if preset ~= 0 then
+-- return false, "unexpected preset dictionary"
+-- end
+-- return true
+-- end
diff --git a/tex/context/base/mkiv/lpdf-ini.lua b/tex/context/base/mkiv/lpdf-ini.lua
index 19f2d7504..050b1fa84 100644
--- a/tex/context/base/mkiv/lpdf-ini.lua
+++ b/tex/context/base/mkiv/lpdf-ini.lua
@@ -18,6 +18,7 @@ local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local formatters = string.formatters
local isboolean = string.is_boolean
local rshift = bit32.rshift
+local osdate, ostime = os.date, os.time
local report_objects = logs.reporter("backend","objects")
local report_finalizing = logs.reporter("backend","finalizing")
@@ -50,199 +51,137 @@ local pdfbackend = {
backends.pdf = pdfbackend
-lpdf = lpdf or { }
-local lpdf = lpdf
-lpdf.flags = lpdf.flags or { } -- will be filled later
-
-local pdfsetinfo = pdf.setinfo
-local pdfsetcatalog = pdf.setcatalog
------ pdfsetnames = pdf.setnames
------ pdfsettrailer = pdf.settrailer
-local pdfsettrailerid = pdf.settrailerid
-
-local pdfsetpageresources = pdf.setpageresources
-local pdfsetpageattributes = pdf.setpageattributes
-local pdfsetpagesattributes = pdf.setpagesattributes
-
-local pdfreserveobject = pdf.reserveobj
-local pdfimmediateobject = pdf.immediateobj
-local pdfdeferredobject = pdf.obj
-local pdfreferenceobject = pdf.refobj
-
-local pdfgetfontname = pdf.getfontname
-local pdfgetfontobjnum = pdf.getfontobjnum
-local pdfgetxformname = pdf.getxformname
-local pdfincludeimage = pdf.includeimage
-local pdfincludechar = pdf.includechar
-local pdfgetpagereference = pdf.getpageref or pdf.pageref -- tex.pdfpageref is obsolete
-local pdfsetfontattributes = pdf.setfontattributes
-
-local setmajorversion = pdf.setmajorversion
-local setminorversion = pdf.setminorversion
-local getmajorversion = pdf.getmajorversion
-local getminorversion = pdf.getminorversion
-
-local setcompresslevel = pdf.setcompresslevel
-local setobjectcompresslevel = pdf.setobjcompresslevel
-local getcompresslevel = pdf.getcompresslevel
-local getobjectcompresslevel = pdf.getobjcompresslevel
-
-local setsuppressoptionalinfo = pdf.setsuppressoptionalinfo
-local setomitcidset = pdf.setomitcidset
-local setomitcharset = pdf.setomitcharset or function() end
-
-local function pdfdisablecommand(command)
- pdf[command] = function()
--- report_blocked("'pdf.%s' is not supported",command)
- end
-end
-
-pdfdisablecommand("setinfo")
-pdfdisablecommand("setcatalog")
-pdfdisablecommand("setnames")
-pdfdisablecommand("settrailer")
-pdfdisablecommand("settrailerid")
-pdfdisablecommand("setomitcidset")
-pdfdisablecommand("setomitcharset")
-pdfdisablecommand("setpageresources")
-pdfdisablecommand("setpageattributes")
-pdfdisablecommand("setpagesattributes")
-pdfdisablecommand("registerannot")
-pdfdisablecommand("reserveobj")
-
-pdf.disablecommand = pdfdisablecommand
-
-updaters.register("backend.update.lpdf",function()
-
- pdfsetinfo = pdf.setinfo
- pdfsetcatalog = pdf.setcatalog
- pdfsettrailerid = pdf.settrailerid
-
- pdfreserveobject = pdf.reserveobj
- pdfimmediateobject = pdf.immediateobj
- pdfdeferredobject = pdf.obj
- pdfreferenceobject = pdf.refobj
- pdfsetfontattributes = pdf.setfontattributes
-
- pdfgetfontname = pdf.getfontname
- pdfgetfontobjnum = pdf.getfontobjnum
- pdfgetxformname = pdf.getxformname
- pdfincludeimage = pdf.includeimage
- pdfincludechar = pdf.includechar
- pdfgetpagereference = pdf.getpageref
-
- setmajorversion = pdf.setmajorversion
- setminorversion = pdf.setminorversion
- getmajorversion = pdf.getmajorversion
- getminorversion = pdf.getminorversion
-
- setcompresslevel = pdf.setcompresslevel
- setobjectcompresslevel = pdf.setobjcompresslevel
- getcompresslevel = pdf.getcompresslevel
- getobjectcompresslevel = pdf.getobjcompresslevel
-
- pdfsetpageresources = pdf.setpageresources
- pdfsetpageattributes = pdf.setpageattributes
- pdfsetpagesattributes = pdf.setpagesattributes
-
- setsuppressoptionalinfo = pdf.setsuppressoptionalinfo
- setomitcidset = pdf.setomitcidset
- setomitcharset = pdf.setomitcharset
-
- pdfdisablecommand("setinfo")
- pdfdisablecommand("setcatalog")
- pdfdisablecommand("settrailerid")
-
- pdfdisablecommand("reserveobj")
- pdfdisablecommand("getfontname")
- pdfdisablecommand("getfontobjnum")
-end)
+lpdf = lpdf or { }
+local lpdf = lpdf
+lpdf.flags = lpdf.flags or { } -- will be filled later
local trace_finalizers = false trackers.register("backend.finalizers", function(v) trace_finalizers = v end)
local trace_resources = false trackers.register("backend.resources", function(v) trace_resources = v end)
local trace_objects = false trackers.register("backend.objects", function(v) trace_objects = v end)
local trace_detail = false trackers.register("backend.detail", function(v) trace_detail = v end)
-function lpdf.settrailerid(id)
- pdfsettrailerid(id)
-end
+do
-function lpdf.setversion(major,minor)
- setmajorversion(major or 1)
- setminorversion(minor or 7)
-end
+ local pdfsetmajorversion, pdfsetminorversion, pdfgetmajorversion, pdfgetminorversion
+ local pdfsetcompresslevel, pdfsetobjectcompresslevel, pdfgetcompresslevel, pdfgetobjectcompresslevel
+ local pdfsetsuppressoptionalinfo, pdfsetomitcidset, pdfsetomitcharset
-function lpdf.getversion(major,minor)
- return getmajorversion(), getminorversion()
-end
+ updaters.register("backend.update.lpdf",function()
+ pdfsetmajorversion = pdf.setmajorversion
+ pdfsetminorversion = pdf.setminorversion
+ pdfgetmajorversion = pdf.getmajorversion
+ pdfgetminorversion = pdf.getminorversion
+
+ pdfsetcompresslevel = pdf.setcompresslevel
+ pdfsetobjectcompresslevel = pdf.setobjcompresslevel
+ pdfgetcompresslevel = pdf.getcompresslevel
+ pdfgetobjectcompresslevel = pdf.getobjcompresslevel
+
+ pdfsetsuppressoptionalinfo = pdf.setsuppressoptionalinfo
+ pdfsetomitcidset = pdf.setomitcidset
+ pdfsetomitcharset = pdf.setomitcharset
+ end)
-function lpdf.majorversion() return getmajorversion() end
-function lpdf.minorversion() return getminorversion() end
+ function lpdf.setversion(major,minor)
+ pdfsetmajorversion(major or 1)
+ pdfsetminorversion(minor or 7)
+ end
-function lpdf.getfontname (id) return pdfgetfontname (id) end
-function lpdf.getfontobjnumber(id) return pdfgetfontobjnum(id) end
+ function lpdf.getversion(major,minor)
+ return pdfgetmajorversion(), pdfgetminorversion()
+ end
-function lpdf.getxformname(id) return pdfgetxformname(id) end
-function lpdf.includeimage(id) return pdfincludeimage(id) end
+ function lpdf.majorversion() return pdfgetmajorversion() end
+ function lpdf.minorversion() return pdfgetminorversion() end
-function lpdf.includechar (f,c) pdfincludechar(f,c) end
-function lpdf.includecharlist(f,c) pdfincludechar(f,c) end -- can be disabled
+ local frozen = false
+ local clevel = 3
+ local olevel = 1
-local frozen = false
-local clevel = 3
-local olevel = 1
+ function lpdf.setcompression(level,objectlevel,freeze)
+ if not frozen then
+ if pdfsetcompresslevel then
+ pdfsetcompresslevel(level or 3)
+ pdfsetobjectcompresslevel(objectlevel or level or 3)
+ else
+ clevel = level
+ olevel = objectlevel
+ end
+ frozen = freeze
+ end
+ end
-function lpdf.setcompression(level,objectlevel,freeze)
- if not frozen then
- if setcompresslevel then
- setcompresslevel(level or 3)
- setobjectcompresslevel(objectlevel or level or 3)
+ function lpdf.getcompression()
+ if pdfgetcompresslevel then
+ return pdfgetcompresslevel(), pdfgetobjectcompresslevel()
else
- clevel = level
- olevel = objectlevel
+ return clevel, olevel
end
- frozen = freeze
end
-end
-function lpdf.getcompression()
- if getcompresslevel then
- return getcompresslevel(), getobjectcompresslevel()
- else
- return clevel, olevel
+ function lpdf.compresslevel()
+ if pdfgetcompresslevel then
+ return pdfgetcompresslevel()
+ else
+ return clevel
+ end
end
-end
-function lpdf.compresslevel()
- if getcompresslevel then
- return getcompresslevel()
- else
- return clevel
+ function lpdf.objectcompresslevel()
+ if pdfgetobjectcompresslevel then
+ return pdfgetobjectcompresslevel()
+ else
+ return olevel
+ end
end
-end
-function lpdf.objectcompresslevel()
- if getobjectcompresslevel then
- return getobjectcompresslevel()
- else
- return olevel
+ function lpdf.setsuppressoptionalinfo(n)
+ if pdfsetsuppressoptionalinfo then
+ pdfsetsuppressoptionalinfo(n) -- todo
+ end
end
-end
-function lpdf.setsuppressoptionalinfo(n)
- if setsuppressoptionalinfo then
- setsuppressoptionalinfo(n) -- todo
+ function lpdf.setomitcidset(v)
+ return pdfsetomitcidset(v)
+ end
+
+ function lpdf.setomitcharset(v)
+ return pdfsetomitcharset(v)
end
-end
-function lpdf.setomitcidset(v)
- return setomitcidset(v)
end
-function lpdf.setomitcharset(v)
- return setomitcharset(v)
+do
+
+ local pdfgetxformname, pdfincludeimage
+
+ updaters.register("backend.update.lpdf",function()
+ pdfgetxformname = pdf.getxformname
+ pdfincludeimage = pdf.includeimage
+ end)
+
+ function lpdf.getxformname(id) return pdfgetxformname(id) end
+ function lpdf.includeimage(id) return pdfincludeimage(id) end
+
end
+ local pdfsetpageresources, pdfsetpageattributes, pdfsetpagesattributes
+ local pdfreserveobject, pdfimmediateobject, pdfdeferredobject, pdfreferenceobject
+ local pdfgetpagereference
+
+ updaters.register("backend.update.lpdf",function()
+ pdfreserveobject = pdf.reserveobj
+ pdfimmediateobject = pdf.immediateobj
+ pdfdeferredobject = pdf.obj
+ pdfreferenceobject = pdf.refobj
+
+ pdfgetpagereference = pdf.getpageref
+
+ pdfsetpageresources = pdf.setpageresources
+ pdfsetpageattributes = pdf.setpageattributes
+ pdfsetpagesattributes = pdf.setpagesattributes
+ end)
+
local jobpositions = job.positions
local getpos = jobpositions.getpos
@@ -254,28 +193,19 @@ jobpositions.registerhandlers {
do
- local pdfgetmatrix = pdf.getmatrix
- local pdfhasmatrix = pdf.hasmatrix
- local pdfprint = pdf.print
+ local pdfgetmatrix, pdfhasmatrix, pdfprint
- -- todo
+ updaters.register("backend.update.lpdf",function()
+ pdfgetmatrix = pdf.getmatrix
+ pdfhasmatrix = pdf.hasmatrix
+ pdfprint = pdf.print
+ end)
function lpdf.print(...)
return pdfprint(...)
end
- pdfbackend.codeinjections.print = lpdf.print
-
- updaters.register("backend.update.lpdf",function()
- pdfprint = pdf.print
- end)
-
- -- todo
-
- updaters.register("backend.update.lpdf",function()
- pdfhasmatrix = pdf.hasmatrix
- pdfgetmatrix = pdf.getmatrix
- end)
+ pdfbackend.codeinjections.print = lpdf.print -- will go
-- local function transform(llx,lly,urx,ury,rx,sx,sy,ry)
-- local x1 = llx * rx + lly * sy
@@ -524,7 +454,9 @@ do
tostring_d = function(t,contentonly,key)
if next(t) then
- local r, n, e = { }, 0
+ local r = { }
+ local n = 0
+ local e
for k, v in next, t do
if k == "__extra__" then
e = v
@@ -1176,6 +1108,18 @@ callbacks.register("finish_pdffile", lpdf.finalizedocument)
do
+ local pdfsetinfo, pdfsetcatalog, pdfsettrailerid -- pdfsetnames pdfsettrailer
+
+ updaters.register("backend.update.lpdf",function()
+ pdfsetinfo = pdf.setinfo
+ pdfsetcatalog = pdf.setcatalog
+ pdfsettrailerid = pdf.settrailerid
+ end)
+
+ function lpdf.settrailerid(id)
+ pdfsettrailerid(id)
+ end
+
-- some minimal tracing, handy for checking the order
local function trace_set(what,key)
@@ -1390,7 +1334,8 @@ end
-- in strc-bkm: lpdf.registerdocumentfinalizer(function() structures.bookmarks.place() end,1)
function lpdf.rotationcm(a)
- local s, c = sind(a), cosd(a)
+ local s = sind(a)
+ local c = cosd(a)
return format("%.6F %.6F %.6F %.6F 0 0 cm",c,s,-s,c)
end
@@ -1439,8 +1384,13 @@ do
lpdf.settime(tonumber(resolvers.variable("start_time")) or tonumber(resolvers.variable("SOURCE_DATE_EPOCH"))) -- bah
function lpdf.pdftimestamp(str)
- local Y, M, D, h, m, s, Zs, Zh, Zm = match(str,"^(%d%d%d%d)%-(%d%d)%-(%d%d)T(%d%d):(%d%d):(%d%d)([%+%-])(%d%d):(%d%d)$")
- return Y and format("D:%s%s%s%s%s%s%s%s'%s'",Y,M,D,h,m,s,Zs,Zh,Zm)
+ local t = type(str)
+ if t == "string" then
+ local Y, M, D, h, m, s, Zs, Zh, Zm = match(str,"^(%d%d%d%d)%-(%d%d)%-(%d%d)T(%d%d):(%d%d):(%d%d)([%+%-])(%d%d):(%d%d)$")
+ return Y and format("D:%s%s%s%s%s%s%s%s'%s'",Y,M,D,h,m,s,Zs,Zh,Zm)
+ else
+ return osdate("D:%Y%m%d%H%M%S",t == "number" and str or ostime()) -- maybe "!D..." : universal time
+ end
end
function lpdf.id(date)
@@ -1680,23 +1630,30 @@ end
do
- local pdf_includechar = pdf.includechar
- local pdf_includefont = pdf.includefont
- local pdf_setmapfile = pdf.mapfile
- local pdf_setmapline = pdf.mapline
+ local pdfincludechar, pdfincludecharlist, pdfincludefont
+ local pdfgetfontname, pdfgetfontobjnum
+ local pdfsetmapfile, pdfsetmapline
updaters.register("backend.update.lpdf",function()
- pdf_includechar = pdf.includechar
- pdf_includefont = pdf.includefont
- pdf_setmapfile = pdf.mapfile
- pdf_setmapline = pdf.mapline
+ pdfincludechar = pdf.includechar
+ pdfincludefont = pdf.includefont
+ pdfincludecharlist = pdf.includecharlist
+ pdfgetfontname = pdf.getfontname
+ pdfgetfontobjnum = pdf.getfontobjnum
+ pdfsetmapfile = pdf.mapfile
+ pdfsetmapline = pdf.mapline
end)
- function lpdf.includechar(...) pdf_includechar(...) end
- function lpdf.includefont(...) pdf_includefont(...) end
+ function lpdf.includechar(f,c) pdfincludechar(f,c) end
+ function lpdf.includefont(...) pdfincludefont(...) end
+
+ function lpdf.includecharlist(f,c) pdfincludecharlist(f,c) end -- can be disabled
+
+ function lpdf.getfontname (id) return pdfgetfontname (id) end
+ function lpdf.getfontobjnumber(id) return pdfgetfontobjnum(id) end
- function lpdf.setmapfile(...) pdf_setmapfile(...) end
- function lpdf.setmapline(...) pdf_setmapline(...) end
+ function lpdf.setmapfile(...) pdfsetmapfile(...) end
+ function lpdf.setmapline(...) pdfsetmapline(...) end
end
diff --git a/tex/context/base/mkiv/lpdf-mis.lua b/tex/context/base/mkiv/lpdf-mis.lua
index 1d2e07310..77f11918b 100644
--- a/tex/context/base/mkiv/lpdf-mis.lua
+++ b/tex/context/base/mkiv/lpdf-mis.lua
@@ -268,7 +268,9 @@ local function flushjavascripts()
local a = pdfarray()
local pdf_javascript = pdfconstant("JavaScript")
for i=1,#t do
- local name, script = t[i][1], t[i][2]
+ local ti = t[i]
+ local name = ti[1]
+ local script = ti[2]
local j = pdfdictionary {
S = pdf_javascript,
JS = pdfreference(pdfflushstreamobject(script)),
diff --git a/tex/context/base/mkiv/lpdf-nod.lua b/tex/context/base/mkiv/lpdf-nod.lua
index d5c1f6b46..8bcf18c62 100644
--- a/tex/context/base/mkiv/lpdf-nod.lua
+++ b/tex/context/base/mkiv/lpdf-nod.lua
@@ -6,7 +6,7 @@ if not modules then modules = { } end modules ['lpdf-nod'] = {
license = "see context related readme files"
}
-if CONTEXTLMTXMODE then
+if CONTEXTLMTXMODE > 1 then
return
end
diff --git a/tex/context/base/mkiv/lpdf-pde.lua b/tex/context/base/mkiv/lpdf-pde.lua
index 9d14f8f5e..c1680137d 100644
--- a/tex/context/base/mkiv/lpdf-pde.lua
+++ b/tex/context/base/mkiv/lpdf-pde.lua
@@ -1003,7 +1003,15 @@ if img then do
return openpdf(str,userpassword,ownerpassword,true)
end
- local function querypdf(pdfdoc,pagenumber)
+ local sizes = {
+ crop = "CropBox",
+ media = "MediaBox",
+ bleed = "BleedBox",
+ art = "ArtBox",
+ trim = "TrimBox",
+ }
+
+ local function querypdf(pdfdoc,pagenumber,size)
if pdfdoc then
if not pagenumber then
pagenumber = 1
@@ -1011,9 +1019,9 @@ if img then do
local root = pdfdoc.Catalog
local page = pdfdoc.pages[pagenumber]
if page then
- -- todo
+ local sizetag = sizes[size or "crop"] or sizes.cro
local mediabox = page.MediaBox or { 0, 0, 0, 0 }
- local cropbox = page.CropBox or mediabox
+ local cropbox = page[sizetag] or mediabox
return {
filename = pdfdoc.filename,
pagenumber = pagenumber,
diff --git a/tex/context/base/mkiv/lpdf-wid.lua b/tex/context/base/mkiv/lpdf-wid.lua
index a929ed2ce..a538a9ad2 100644
--- a/tex/context/base/mkiv/lpdf-wid.lua
+++ b/tex/context/base/mkiv/lpdf-wid.lua
@@ -268,6 +268,7 @@ function codeinjections.embedfile(specification)
local usedname = specification.usedname
local filetype = specification.filetype
local compress = specification.compress
+ local mimetype = specification.mimetype or specification.mime
if filename == "" then
filename = nil
end
@@ -317,7 +318,6 @@ function codeinjections.embedfile(specification)
filetype = name and (filename and file.suffix(filename)) or "txt"
end
savename = file.addsuffix(savename,filetype) -- type is mandate for proper working in viewer
- local mimetype = specification.mimetype
local a = pdfdictionary {
Type = pdfconstant("EmbeddedFile"),
Subtype = mimetype and mimetype ~= "" and pdfconstant(mimetype) or nil,
@@ -327,17 +327,24 @@ function codeinjections.embedfile(specification)
f = pdfflushstreamobject(data,a)
specification.data = true -- signal that still data but already flushed
else
- local foundname = specification.foundname or filename
+ local foundname = specification.foundname or filename
+ local attributes = lfs.attributes(foundname)
+ if attributes then
+ a.Params = {
+ Size = attributes.size,
+ ModDate = lpdf.pdftimestamp(attributes.modification),
+ }
+ end
f = pdfflushstreamfileobject(foundname,a,compress)
end
local d = pdfdictionary {
- Type = pdfconstant("Filespec"),
- F = pdfstring(savename),
- -- UF = pdfstring(savename),
- UF = pdfunicode(savename),
- EF = pdfdictionary { F = pdfreference(f) },
- Desc = title ~= "" and pdfunicode(title) or nil,
- -- AFRelationship = pdfconstant("Source"), -- some day maybe, not mandate
+ Type = pdfconstant("Filespec"),
+ F = pdfstring(savename),
+ -- UF = pdfstring(savename),
+ UF = pdfunicode(savename),
+ EF = pdfdictionary { F = pdfreference(f) },
+ Desc = title ~= "" and pdfunicode(title) or nil,
+ AFRelationship = pdfconstant("Unspecified"), -- Supplement, Data, Source, Alternative, Data
}
local r = pdfreference(pdfflushobject(d))
filestreams[hash] = r
diff --git a/tex/context/base/mkiv/luat-bas.mkiv b/tex/context/base/mkiv/luat-bas.mkiv
index b972fc180..0add4ce69 100644
--- a/tex/context/base/mkiv/luat-bas.mkiv
+++ b/tex/context/base/mkiv/luat-bas.mkiv
@@ -13,6 +13,7 @@
\writestatus{loading}{ConTeXt Lua Macros / Basic Lua Libraries}
+\registerctxluafile{l-bit32} {} % before sandbox
\registerctxluafile{l-lua} {} % before sandbox
\registerctxluafile{l-macro} {}
\registerctxluafile{l-sandbox} {}
diff --git a/tex/context/base/mkiv/luat-cnf.lua b/tex/context/base/mkiv/luat-cnf.lua
index b6ee15083..5e3f026e9 100644
--- a/tex/context/base/mkiv/luat-cnf.lua
+++ b/tex/context/base/mkiv/luat-cnf.lua
@@ -30,6 +30,8 @@ texconfig.nest_size = 1000
texconfig.param_size = 25000
texconfig.save_size = 100000
texconfig.stack_size = 10000
+texconfig.function_size = 32768
+texconfig.properties_size = 65536
local stub = [[
@@ -154,6 +156,8 @@ function texconfig.init()
end
+CONTEXTLMTXMODE = %s
+
-- we provide a qualified path
callback.register('find_format_file',function(name)
@@ -176,6 +180,8 @@ local variablenames = {
param_size = true,
save_size = true,
stack_size = true,
+ function_size = true,
+ properties_size = true,
}
local function makestub()
@@ -212,7 +218,7 @@ local function makestub()
t[#t+1] = format("texconfig.%s=%s",v,tv)
end
end
- io.savedata(name,format("%s\n\n%s",concat(t,"\n"),format(stub,firsttable)))
+ io.savedata(name,format("%s\n\n%s",concat(t,"\n"),format(stub,firsttable,tostring(CONTEXTLMTXMODE) or 0)))
logs.newline()
end
diff --git a/tex/context/base/mkiv/luat-cod.lua b/tex/context/base/mkiv/luat-cod.lua
index 849530f72..c667f3ecc 100644
--- a/tex/context/base/mkiv/luat-cod.lua
+++ b/tex/context/base/mkiv/luat-cod.lua
@@ -30,6 +30,8 @@ texconfig.nest_size = 1000
texconfig.param_size = 25000
texconfig.save_size = 100000
texconfig.stack_size = 10000
+texconfig.function_size = 32768
+texconfig.properties_size = 65536
-- registering bytecode chunks
@@ -142,7 +144,15 @@ if LUATEXVERION == nil then
end
if CONTEXTLMTXMODE == nil then
- CONTEXTLMTXMODE = status.obj_ptr == nil and true or false
+ if status.obj_ptr == nil then
+ CONTEXTLMTXMODE = 2
+ else
+ CONTEXTLMTXMODE = 0
+ for i=1,#arg do if arg[i] == "--c:lmtx" then
+ CONTEXTLMTXMODE, pdf, img = 1, nil, nil
+ break
+ end end
+ end
end
if LUATEXFUNCTIONALITY == nil then
diff --git a/tex/context/base/mkiv/luat-fmt.lua b/tex/context/base/mkiv/luat-fmt.lua
index 2abc47094..586c5948e 100644
--- a/tex/context/base/mkiv/luat-fmt.lua
+++ b/tex/context/base/mkiv/luat-fmt.lua
@@ -19,9 +19,9 @@ local function primaryflags()
if arguments.silent then
flags[#flags+1] = "--interaction=batchmode"
end
- if arguments.jit then
- flags[#flags+1] = "--jiton"
- end
+ -- if arguments.jit then
+ -- flags[#flags+1] = "--jiton"
+ -- end
return concat(flags," ")
end
@@ -51,6 +51,9 @@ local function secondaryflags()
if arguments.strip then
flags[#flags+1] = "--c:strip"
end
+ if arguments.lmtx then
+ flags[#flags+1] = "--c:lmtx"
+ end
return concat(flags," ")
end
@@ -76,6 +79,13 @@ local runners = {
checkers = checkers,
reporter = report_format,
},
+ luametatex = sandbox.registerrunner {
+ name = "make luametatex format",
+ program = "luametatex",
+ template = template,
+ checkers = checkers,
+ reporter = report_format,
+ },
luajittex = sandbox.registerrunner {
name = "make luajittex format",
program = "luajittex",
diff --git a/tex/context/base/mkiv/luat-ini.lua b/tex/context/base/mkiv/luat-ini.lua
index 87883b55d..ffd402c77 100644
--- a/tex/context/base/mkiv/luat-ini.lua
+++ b/tex/context/base/mkiv/luat-ini.lua
@@ -37,7 +37,7 @@ JITSUPPORTED = LUATEXENGINE == "luajittex" or jit
INITEXMODE = status.ini_version
-CONTEXTLMTXMODE = status.obj_ptr == nil and true or false
+CONTEXTLMTXMODE = CONTEXTLMTXMODE or (status.obj_ptr == nil and 2 or 1)
function os.setlocale()
-- no need for a message
diff --git a/tex/context/base/mkiv/luat-lib.mkiv b/tex/context/base/mkiv/luat-lib.mkiv
index d5f6099ca..666032369 100644
--- a/tex/context/base/mkiv/luat-lib.mkiv
+++ b/tex/context/base/mkiv/luat-lib.mkiv
@@ -54,6 +54,10 @@
%registerctxluafile{util-soc-imp-ftp} {}
%registerctxluafile{util-soc-imp-smtp} {}
+\ifcase\contextlmtxmode\else
+ \registerctxluafile{util-zip}{}
+\fi
+
\registerctxluafile{data-ini}{}
\registerctxluafile{data-exp}{}
\registerctxluafile{data-env}{}
diff --git a/tex/context/base/mkiv/luat-run.lua b/tex/context/base/mkiv/luat-run.lua
index 39384b7b1..ed4d5f5e7 100644
--- a/tex/context/base/mkiv/luat-run.lua
+++ b/tex/context/base/mkiv/luat-run.lua
@@ -9,6 +9,7 @@ if not modules then modules = { } end modules ['luat-run'] = {
local next = next
local format, find = string.format, string.find
local insert, remove = table.insert, table.remove
+local osexit = os.exit
-- trace_job_status is also controlled by statistics.enable that is set via the directive system.nostatistics
@@ -64,8 +65,9 @@ local function stop_run()
end
end
if quit then
- if status.setexitcode then
- status.setexitcode(1)
+ local setexitcode = lua.setexitcode or status.setexitcode
+ if setexitcode then
+ setexitcode(1)
if type(quit) == "table" then
logs.newline()
report_tex("quitting due to: %, t",quit)
@@ -117,14 +119,18 @@ end
-- For Taco ...
-local sequencers = utilities.sequencers
-local appendgroup = sequencers.appendgroup
-local appendaction = sequencers.appendaction
-local wrapupactions = sequencers.new { }
+local sequencers = utilities.sequencers
+local appendgroup = sequencers.appendgroup
+local appendaction = sequencers.appendaction
+local wrapupactions = sequencers.new { }
+local cleanupactions = sequencers.new { }
appendgroup(wrapupactions,"system")
appendgroup(wrapupactions,"user")
+appendgroup(cleanupactions,"system")
+appendgroup(cleanupactions,"user")
+
local function wrapup_run()
local runner = wrapupactions.runner
if runner then
@@ -132,10 +138,26 @@ local function wrapup_run()
end
end
+local function cleanup_run()
+ local runner = cleanupactions.runner
+ if runner then
+ runner()
+ end
+end
+
function luatex.wrapup(action)
appendaction(wrapupactions,"user",action)
end
+function luatex.cleanup(action)
+ appendaction(cleanupactions,"user",action)
+end
+
+function luatex.abort()
+ cleanup_run()
+ osexit(1)
+end
+
appendaction(wrapupactions,"system",synctex.wrapup)
-- this can be done later
@@ -243,7 +265,7 @@ local function report_stop()
end
end
-if not CONTEXTLMTXMODE then
+if CONTEXTLMTXMODE < 2 then
local types = {
"data",
diff --git a/tex/context/base/mkiv/lxml-aux.lua b/tex/context/base/mkiv/lxml-aux.lua
index 78cf1d6bd..ed0f03fd8 100644
--- a/tex/context/base/mkiv/lxml-aux.lua
+++ b/tex/context/base/mkiv/lxml-aux.lua
@@ -134,10 +134,12 @@ end
function xml.collect_tags(root, pattern, nonamespace)
local collected = xmlapplylpath(root,pattern)
if collected then
- local t, n = { }, 0
+ local t = { }
+ local n = 0
for c=1,#collected do
- local e = collected[c]
- local ns, tg = e.ns, e.tg
+ local e = collected[c]
+ local ns = e.ns
+ local tg = e.tg
n = n + 1
if nonamespace then
t[n] = tg
@@ -226,7 +228,7 @@ function xml.delete(root,pattern)
if trace_manipulations then
report('deleting',pattern,c,e)
end
- local d = p.dt
+ local d = p.dt
local ni = e.ni
if ni <= #d then
if false then
@@ -313,8 +315,10 @@ local function inject_element(root,pattern,whatever,prepend)
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
local function inject_e(e)
- local r = e.__p__
- local d, k, rri = r.dt, e.ni, r.ri
+ local r = e.__p__
+ local d = r.dt
+ local k = e.ni
+ local rri = r.ri
local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
if edt then
local be, af
@@ -354,7 +358,8 @@ local function insert_element(root,pattern,whatever,before) -- todo: element als
local collected = element and xmlapplylpath(root,pattern)
local function insert_e(e)
local r = e.__p__
- local d, k = r.dt, e.ni
+ local d = r.dt
+ local k = e.ni
if not before then
k = k + 1
end
@@ -860,8 +865,10 @@ function xml.separate(x,pattern)
report_xml("warning: xml.separate changes root")
x = d
end
- local t, n = { "\n" }, 1
- local i, nd = 1, #d
+ local t = { "\n" }
+ local n = 1
+ local i = 1
+ local nd = #d
while i <= nd do
while i <= nd do
local di = d[i]
diff --git a/tex/context/base/mkiv/lxml-inf.lua b/tex/context/base/mkiv/lxml-inf.lua
index 8d99d6270..6fb64c0fe 100644
--- a/tex/context/base/mkiv/lxml-inf.lua
+++ b/tex/context/base/mkiv/lxml-inf.lua
@@ -17,7 +17,8 @@ local getid = lxml.getid
local status, stack
local function get(e,d)
- local ns, tg = e.ns, e.tg
+ local ns = e.ns
+ local tg = e.tg
local name = tg
if ns ~= "" then name = ns .. ":" .. tg end
stack[d] = name
diff --git a/tex/context/base/mkiv/lxml-lpt.lua b/tex/context/base/mkiv/lxml-lpt.lua
index a80a33f42..392c1a401 100644
--- a/tex/context/base/mkiv/lxml-lpt.lua
+++ b/tex/context/base/mkiv/lxml-lpt.lua
@@ -166,7 +166,8 @@ apply_axis['self'] = function(list)
end
apply_axis['child'] = function(list)
- local collected, c = { }, 0
+ local collected = { }
+ local c = 0
for l=1,#list do
local ll = list[l]
local dt = ll.dt
@@ -240,7 +241,8 @@ local function collect(list,collected,c)
end
apply_axis['descendant'] = function(list)
- local collected, c = { }, 0
+ local collected = { }
+ local c = 0
for l=1,#list do
c = collect(list[l],collected,c)
end
@@ -283,7 +285,8 @@ local function collect(list,collected,c)
end
apply_axis['descendant-or-self'] = function(list)
- local collected, c = { }, 0
+ local collected = { }
+ local c = 0
for l=1,#list do
local ll = list[l]
if ll.special ~= true then -- catch double root
@@ -296,7 +299,8 @@ apply_axis['descendant-or-self'] = function(list)
end
apply_axis['ancestor'] = function(list)
- local collected, c = { }, 0
+ local collected = { }
+ local c = 0
for l=1,#list do
local ll = list[l]
while ll do
@@ -311,7 +315,8 @@ apply_axis['ancestor'] = function(list)
end
apply_axis['ancestor-or-self'] = function(list)
- local collected, c = { }, 0
+ local collected = { }
+ local c = 0
for l=1,#list do
local ll = list[l]
c = c + 1
@@ -328,7 +333,8 @@ apply_axis['ancestor-or-self'] = function(list)
end
apply_axis['parent'] = function(list)
- local collected, c = { }, 0
+ local collected = { }
+ local c = 0
for l=1,#list do
local pl = list[l].__p__
if pl then
@@ -367,7 +373,8 @@ apply_axis['following'] = function(list) -- incomplete
end
apply_axis['preceding'] = function(list) -- incomplete
- -- local collected, c = { }, 0
+ -- local collected = { }
+ -- local c = 0
-- for l=1,#list do
-- local ll = list[l]
-- local p = ll.__p__
@@ -386,7 +393,8 @@ apply_axis['preceding'] = function(list) -- incomplete
end
apply_axis['following-sibling'] = function(list)
- local collected, c = { }, 0
+ local collected = { }
+ local c = 0
for l=1,#list do
local ll = list[l]
local p = ll.__p__
@@ -403,7 +411,8 @@ apply_axis['following-sibling'] = function(list)
end
apply_axis['preceding-sibling'] = function(list)
- local collected, c = { }, 0
+ local collected = { }
+ local c = 0
for l=1,#list do
local ll = list[l]
local p = ll.__p__
@@ -420,7 +429,8 @@ apply_axis['preceding-sibling'] = function(list)
end
apply_axis['reverse-sibling'] = function(list) -- reverse preceding
- local collected, c = { }, 0
+ local collected = { }
+ local c = 0
for l=1,#list do
local ll = list[l]
local p = ll.__p__
@@ -447,7 +457,8 @@ local function apply_nodes(list,directive,nodes)
-- ... currently ignored
local maxn = #nodes
if maxn == 3 then --optimized loop
- local nns, ntg = nodes[2], nodes[3]
+ local nns = nodes[2]
+ local ntg = nodes[3]
if not nns and not ntg then -- wildcard
if directive then
return list
@@ -455,40 +466,47 @@ local function apply_nodes(list,directive,nodes)
return { }
end
else
- local collected, c, m, p = { }, 0, 0, nil
+ local collected = { }
+ local c = 0
+ local m = 0
+ local p = nil
if not nns then -- only check tag
for l=1,#list do
- local ll = list[l]
+ local ll = list[l]
local ltg = ll.tg
if ltg then
if directive then
if ntg == ltg then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
+ local llp = ll.__p__ ; if llp ~= p then p = llp ; m = 1 else m = m + 1 end
c = c + 1
- collected[c], ll.mi = ll, m
+ collected[c] = ll
+ ll.mi = m
end
elseif ntg ~= ltg then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
+ local llp = ll.__p__ ; if llp ~= p then p = llp ; m = 1 else m = m + 1 end
c = c + 1
- collected[c], ll.mi = ll, m
+ collected[c] = ll
+ ll.mi = m
end
end
end
elseif not ntg then -- only check namespace
for l=1,#list do
- local ll = list[l]
+ local ll = list[l]
local lns = ll.rn or ll.ns
if lns then
if directive then
if lns == nns then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
+ local llp = ll.__p__ ; if llp ~= p then p = llp ; m = 1 else m = m + 1 end
c = c + 1
- collected[c], ll.mi = ll, m
+ collected[c] = ll
+ ll.mi = m
end
elseif lns ~= nns then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
+ local llp = ll.__p__ ; if llp ~= p then p = llp ; m = 1 else m = m + 1 end
c = c + 1
- collected[c], ll.mi = ll, m
+ collected[c] = ll
+ ll.mi = m
end
end
end
@@ -501,14 +519,16 @@ local function apply_nodes(list,directive,nodes)
local ok = ltg == ntg and lns == nns
if directive then
if ok then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
+ local llp = ll.__p__ ; if llp ~= p then p = llp ; m = 1 else m = m + 1 end
c = c + 1
- collected[c], ll.mi = ll, m
+ collected[c] = ll
+ ll.mi = m
end
elseif not ok then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
+ local llp = ll.__p__ ; if llp ~= p then p = llp ; m = 1 else m = m + 1 end
c = c + 1
- collected[c], ll.mi = ll, m
+ collected[c] = ll
+ ll.mi = m
end
end
end
@@ -516,15 +536,19 @@ local function apply_nodes(list,directive,nodes)
return collected
end
else
- local collected, c, m, p = { }, 0, 0, nil
+ local collected = { }
+ local c = 0
+ local m = 0
+ local p = nil
for l=1,#list do
- local ll = list[l]
+ local ll = list[l]
local ltg = ll.tg
if ltg then
local lns = ll.rn or ll.ns
- local ok = false
+ local ok = false
for n=1,maxn,3 do
- local nns, ntg = nodes[n+1], nodes[n+2]
+ local nns = nodes[n+1]
+ local ntg = nodes[n+2]
ok = (not ntg or ltg == ntg) and (not nns or lns == nns)
if ok then
break
@@ -532,14 +556,16 @@ local function apply_nodes(list,directive,nodes)
end
if directive then
if ok then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
+ local llp = ll.__p__ ; if llp ~= p then p = llp ; m = 1 else m = m + 1 end
c = c + 1
- collected[c], ll.mi = ll, m
+ collected[c] = ll
+ ll.mi = m
end
elseif not ok then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
+ local llp = ll.__p__ ; if llp ~= p then p = llp ; m = 1 else m = m + 1 end
c = c + 1
- collected[c], ll.mi = ll, m
+ collected[c] = ll
+ ll.mi = m
end
end
end
@@ -550,7 +576,8 @@ end
local quit_expression = false
local function apply_expression(list,expression,order)
- local collected, c = { }, 0
+ local collected = { }
+ local c = 0
quit_expression = false
for l=1,#list do
local ll = list[l]
@@ -947,7 +974,8 @@ local function tagstostring(list)
local t = { }
for i=1, #list do
local li = list[i]
- local ns, tg = li.ns, li.tg
+ local ns = li.ns
+ local tg = li.tg
if not ns or ns == "" then ns = "*" end
if not tg or tg == "" then tg = "*" end
t[i] = (tg == "@rt@" and "[root]") or format("%s:%s",ns,tg)
@@ -1412,7 +1440,8 @@ expressions.name = function(e,n) -- ns + tg
if n == 0 then
found = type(e) == "table" and e
elseif n < 0 then
- local d, k = e.__p__.dt, e.ni
+ local d = e.__p__.dt
+ local k = e.ni
for i=k-1,1,-1 do
local di = d[i]
if type(di) == "table" then
@@ -1425,7 +1454,8 @@ expressions.name = function(e,n) -- ns + tg
end
end
else
- local d, k = e.__p__.dt, e.ni
+ local d = e.__p__.dt
+ local k = e.ni
for i=k+1,#d,1 do
local di = d[i]
if type(di) == "table" then
@@ -1439,7 +1469,8 @@ expressions.name = function(e,n) -- ns + tg
end
end
if found then
- local ns, tg = found.rn or found.ns or "", found.tg
+ local ns = found.rn or found.ns or ""
+ local tg = found.tg
if ns ~= "" then
return ns .. ":" .. tg
else
@@ -1459,7 +1490,8 @@ expressions.tag = function(e,n) -- only tg
if n == 0 then
found = (type(e) == "table") and e -- seems to fail
elseif n < 0 then
- local d, k = e.__p__.dt, e.ni
+ local d = e.__p__.dt
+ local k = e.ni
for i=k-1,1,-1 do
local di = d[i]
if type(di) == "table" then
@@ -1472,7 +1504,8 @@ expressions.tag = function(e,n) -- only tg
end
end
else
- local d, k = e.__p__.dt, e.ni
+ local d = e.__p__.dt
+ local k = e.ni
for i=k+1,#d,1 do
local di = d[i]
if type(di) == "table" then
diff --git a/tex/context/base/mkiv/math-ali.mkiv b/tex/context/base/mkiv/math-ali.mkiv
index ecfac6887..592a3441c 100644
--- a/tex/context/base/mkiv/math-ali.mkiv
+++ b/tex/context/base/mkiv/math-ali.mkiv
@@ -968,9 +968,14 @@
{\c_math_eqalign_column\zerocount
\rawprocesscommacommand[\mathmatrixparameter\c!align]\math_matrix_set_columns_step}
+\newcount\c_math_eqalign_column_saved
+\newcount\c_math_eqalign_first_saved
+
\unexpanded\def\math_matrix_start#1%
{\begingroup
\globalpushmacro\c_math_matrix_first
+ \c_math_eqalign_column_saved\c_math_eqalign_column
+ \c_math_eqalign_first_saved \c_math_eqalign_first
\edef\currentmathmatrix{#1}%
\dosingleempty\math_matrix_start_indeed}
@@ -985,6 +990,8 @@
\def\math_matrix_stop
{\math_matrix_stop_processing
+ \global\c_math_eqalign_first\c_math_eqalign_first_saved
+ \global\c_math_eqalign_column\c_math_eqalign_column_saved
\globalpopmacro\c_math_matrix_first
\endgroup}
diff --git a/tex/context/base/mkiv/math-dim.lua b/tex/context/base/mkiv/math-dim.lua
index 72b9d7e50..eb7adb53f 100644
--- a/tex/context/base/mkiv/math-dim.lua
+++ b/tex/context/base/mkiv/math-dim.lua
@@ -157,7 +157,8 @@ function mathematics.dimensions(dimens) -- beware, dimens get spoiled
for variable, styles in next, defaults do
local tt = { }
for style, default in next, styles do
- local one, two = default[1], default[2]
+ local one = default[1]
+ local two = default[2]
local value = dimens[one]
if value then
tt[style] = value
diff --git a/tex/context/base/mkiv/math-fbk.lua b/tex/context/base/mkiv/math-fbk.lua
index 50c977178..963461de5 100644
--- a/tex/context/base/mkiv/math-fbk.lua
+++ b/tex/context/base/mkiv/math-fbk.lua
@@ -384,7 +384,8 @@ end
virtualcharacters[0x203E] = function(data)
local target = data.target
- local height, depth = 0, 0
+ local height = 0
+ local depth = 0
-- local mathparameters = target.mathparameters
-- if mathparameters then
-- height = mathparameters.OverbarVerticalGap
diff --git a/tex/context/base/mkiv/math-fen.mkiv b/tex/context/base/mkiv/math-fen.mkiv
index 3a32f9fb8..6c6724bf5 100644
--- a/tex/context/base/mkiv/math-fen.mkiv
+++ b/tex/context/base/mkiv/math-fen.mkiv
@@ -490,31 +490,31 @@
\installmathfencepair \letteropenbrace \Lbrace \letterclosebrace \Rbrace % as we escape in mp textexts
-\installmathfencepair . \Lnothing . \Rnothing
-\installmathfencepair . \Rnothingmirrored . \Lnothingmirrored
+\installmathfencepair . \Lnothing . \Rnothing
+\installmathfencepair . \Rnothingmirrored . \Lnothingmirrored
-\installmathfencepair [ \Lbracket ] \Rbracket
-\installmathfencepair ] \Rbracketmirrored [ \Lbracketmirrored
+\installmathfencepair [ \Lbracket ] \Rbracket
+\installmathfencepair ] \Rbracketmirrored [ \Lbracketmirrored
-\installmathfencepair ( \Lparenthesis ) \Rparenthesis
-\installmathfencepair ) \Rparentmirrored ( \Lparentmirrored
+\installmathfencepair ( \Lparenthesis ) \Rparenthesis
+\installmathfencepair ) \Rparenthesismirrored ( \Lparenthesismirrored
-\installmathfencepair < \Langle > \Rangle
-\installmathfencepair > \Ranglemirrored < \Langlemirrored
+\installmathfencepair < \Langle > \Rangle
+\installmathfencepair > \Ranglemirrored < \Langlemirrored
-\installmathfencepair / \Lsolidus / \Rsolidus
-%installmathfencepair / \Rsolidusmirrored / \Lsolidusmirrored
+\installmathfencepair / \Lsolidus / \Rsolidus
+%installmathfencepair / \Rsolidusmirrored / \Lsolidusmirrored
-\installmathfencepair | \Lbar | \Rbar
-%installmathfencepair | \Rbarmirrored | \Lbarmirrored
+\installmathfencepair | \Lbar | \Rbar
+%installmathfencepair | \Rbarmirrored | \Lbarmirrored
-\installmathfencepair ⌊ \Lfloor ⌋ \Rfloor
-\installmathfencepair ⌋ \Rfloormirrored ⌊ \Lfloormirrored
-\installmathfencepair ⌈ \Lceiling ⌉ \Rceiling
-\installmathfencepair ⌉ \Rceilingmirrored ⌈ \Lceilingmirrored
+\installmathfencepair ⌊ \Lfloor ⌋ \Rfloor
+\installmathfencepair ⌋ \Rfloormirrored ⌊ \Lfloormirrored
+\installmathfencepair ⌈ \Lceiling ⌉ \Rceiling
+\installmathfencepair ⌉ \Rceilingmirrored ⌈ \Lceilingmirrored
-\installmathfencepair ⟨ \Langle ⟩ \Rangle
-\installmathfencepair ⟩ \Ranglemirrored ⟨ \Langlemirrored
+\installmathfencepair ⟨ \Langle ⟩ \Rangle
+\installmathfencepair ⟩ \Ranglemirrored ⟨ \Langlemirrored
\installmathfencepair ⟪ \Ldoubleangle ⟫ \Rdoubleangle
\installmathfencepair ⟫ \Rdoubleanglemirrored ⟪ \Ldoubleanglemirrored
@@ -525,10 +525,10 @@
\installmathfencepair ⦀ \Ltriplebar ⦀ \Rtriplebar
%installmathfencepair ⦀ \Rtriplebarmirrored ⦀ \Ltriplebarmirrored
-% \installmathfencepair { \Lbrace } \Rbrace
-% \installmathfencepair } \Rbracemirrored { \Lbracemirrored
+% \installmathfencepair { \Lbrace } \Rbrace
+% \installmathfencepair } \Rbracemirrored { \Lbracemirrored
-\installmathfencepair ⦗ \Linterv ⦘ \Rinterv
+\installmathfencepair ⦗ \Linterval ⦘ \Rinterval
\appendtoks
\ignorediscretionaries % so $\mtext{a|b}$ works, this is ok because it's an \hbox
diff --git a/tex/context/base/mkiv/math-ini.lua b/tex/context/base/mkiv/math-ini.lua
index 66c08a76a..7a8419702 100644
--- a/tex/context/base/mkiv/math-ini.lua
+++ b/tex/context/base/mkiv/math-ini.lua
@@ -289,7 +289,8 @@ function mathematics.define(family)
local data = characters.data
for unicode, character in sortedhash(data) do
local symbol = character.mathsymbol
- local mset, dset = true, true
+ local mset = true
+ local dset = true
if symbol then
local other = data[symbol]
local class = other.mathclass
diff --git a/tex/context/base/mkiv/math-ini.mkiv b/tex/context/base/mkiv/math-ini.mkiv
index 50da1a400..3c27bbf07 100644
--- a/tex/context/base/mkiv/math-ini.mkiv
+++ b/tex/context/base/mkiv/math-ini.mkiv
@@ -268,8 +268,8 @@
\def\math_m_yes_text_openedup#1%
{\setbox\scratchbox\hbox\bgroup
- \normalstartimath
\the\everyswitchmathematics\relax
+ \normalstartimath
#1%
\normalstopimath
\egroup
@@ -285,8 +285,8 @@
\endgroup}
\def\math_m_yes_text_normal#1%
- {\normalstartimath
- \the\everyswitchmathematics\relax
+ {\the\everyswitchmathematics\relax
+ \normalstartimath
#1%
\normalstopimath
\endgroup}
@@ -436,6 +436,16 @@
% if there were many features we could have a feature pass over math nodes but it makes no
% sense now so we have commands to deal with it
+% \enabletrackers[math.alternates]
+% \setupbodyfont[lucidaot]
+%
+% \startTEXpage
+% \setupmathematics[stylealternative={reset}]$x+\mathcal A$\par
+% \setupmathematics[stylealternative={reset,calligraphic}]$x+\mathcal A$\par
+% \setupmathematics[stylealternative={reset,italic}]$x+\mathcal A$\par
+% \setupmathematics[stylealternative={reset,calligraphic,italic}]$x+\mathcal A$
+% \stopTEXpage
+
\unexpanded\def\mathaltcalligraphic{\math_set_font_alternate{calligraphic}\cal} % set via goody file
\unexpanded\def\mathaltitalic {\math_set_font_alternate{italic}} % set via goody file
\unexpanded\def\mathslashedzero {\begingroup\math_set_font_alternate{zero}∅\endgroup} % set via goody file or automatic
diff --git a/tex/context/base/mkiv/math-noa.lua b/tex/context/base/mkiv/math-noa.lua
index 11baaf413..376767227 100644
--- a/tex/context/base/mkiv/math-noa.lua
+++ b/tex/context/base/mkiv/math-noa.lua
@@ -778,7 +778,8 @@ do
if subtype == leftfence_code or subtype == rightfence_code then
local a = getattr(pointer,a_mathsize)
if a and a > 0 then
- local method, size = div(a,100), a % 100
+ local method = div(a,100)
+ local size = a % 100
setattr(pointer,a_mathsize,0)
local delimiter = getfield(pointer,"delim")
local chr = getchar(delimiter)
@@ -1335,7 +1336,7 @@ do
local resets = mathalternates.resets
attribute = presets[tag]
if not attribute then
- attribute = 0
+ attribute = 0
local alternates = mathalternates.alternates
for s in gmatch(tag,"[^, ]+") do
if s == v_reset then
@@ -1409,13 +1410,15 @@ do
alt = otf.getalternate(fontdata[fontid],char,what.feature,what.value) or false
if alt == char then
alt = false
- elseif trace_alternates then
- report_alternates("alternate %a, value %a, replacing glyph %U by glyph %U",
- tostring(what.feature),tostring(what.value),getchar(pointer),alt)
end
hashes[i][char] = alt
end
if alt then
+ if trace_alternates then
+ local what = attributes[r]
+ report_alternates("alternate %a, value %a, replacing glyph %U by glyph %U",
+ tostring(what.feature),tostring(what.value),getchar(pointer),alt)
+ end
setchar(pointer,alt)
break
end
diff --git a/tex/context/base/mkiv/math-vfu.lua b/tex/context/base/mkiv/math-vfu.lua
index f19e9d61b..ed6f69f41 100644
--- a/tex/context/base/mkiv/math-vfu.lua
+++ b/tex/context/base/mkiv/math-vfu.lua
@@ -405,23 +405,32 @@ local function jointhree(main,characters,id,size,unicode,u1,d12,u2,d23,u3)
end
local function stack(main,characters,id,size,unicode,u1,d12,u2)
- local c1, c2 = characters[u1], characters[u2]
- if c1 and c2 then
- local w1, h1, d1 = c1.width, c1.height, c1.depth
- local w2, h2, d2 = c2.width, c2.height, c2.depth
- local mu = size/18
- characters[unicode] = {
- width = w1,
- height = h1 + h2 + d12,
- depth = d1,
- commands = {
- { "slot", id, u1 },
- leftcommand[w1/2 + w2/2],
- downcommand[-h1 + d2 -d12*mu],
- { "slot", id, u2 },
- }
- }
+ local c1 = characters[u1]
+ if not c1 then
+ return
end
+ local c2 = characters[u2]
+ if not c2 then
+ return
+ end
+ local w1 = c1.width or 0
+ local h1 = c1.height or 0
+ local d1 = c1.depth or 0
+ local w2 = c2.width or 0
+ local h2 = c2.height or 0
+ local d2 = c2.depth or 0
+ local mu = size/18
+ characters[unicode] = {
+ width = w1,
+ height = h1 + h2 + d12,
+ depth = d1,
+ commands = {
+ { "slot", id, u1 },
+ leftcommand[w1/2 + w2/2],
+ downcommand[-h1 + d2 -d12*mu],
+ { "slot", id, u2 },
+ }
+ }
end
local function repeated(main,characters,id,size,unicode,u,n,private,fraction) -- math-fbk.lua
@@ -429,8 +438,8 @@ local function repeated(main,characters,id,size,unicode,u,n,private,fraction) --
if c then
local width = c.width
local italic = fraction*width -- c.italic or 0 -- larger ones have funny italics
- local tc = { "slot", id, u }
- local tr = leftcommand[italic] -- see hack elsewhere
+ local tc = { "slot", id, u }
+ local tr = leftcommand[italic] -- see hack elsewhere
local commands = { }
for i=1,n-1 do
commands[#commands+1] = tc
@@ -610,7 +619,8 @@ setmetatableindex(reverse, function(t,name)
if trace_virtual then
report_virtual("initializing math vector %a",name)
end
- local m, r = mathencodings[name], { }
+ local m = mathencodings[name]
+ local r = { }
for u, i in next, m do
r[i] = u
end
@@ -700,13 +710,17 @@ end
vfmath.copy_glyph = copy_glyph
function vfmath.define(specification,set,goodies)
- local name = specification.name -- symbolic name
- local size = specification.size -- given size
- local loaded, fontlist, names, main = { }, { }, { }, nil
- local start = (trace_virtual or trace_timings) and os.clock()
- local okset, n = { }, 0
+ local name = specification.name -- symbolic name
+ local size = specification.size -- given size
+ local loaded = { }
+ local fontlist = { }
+ local names = { }
+ local main = nil
+ local start = (trace_virtual or trace_timings) and os.clock()
+ local okset = { }
+ local n = 0
for s=1,#set do
- local ss = set[s]
+ local ss = set[s]
local ssname = ss.name
if add_optional and ss.optional then
if trace_virtual then
@@ -850,11 +864,11 @@ function vfmath.define(specification,set,goodies)
elseif add_optional and ss.optional then
-- skip, redundant
else
- local newparameters = fs.parameters
+ local newparameters = fs.parameters
local newmathparameters = fs.mathparameters
if newmathparameters then
if not parameters_done or ss.parameters then
- mathparameters = newmathparameters
+ mathparameters = newmathparameters
parameters_done = true
end
elseif not newparameters then
@@ -889,7 +903,7 @@ function vfmath.define(specification,set,goodies)
-- report_virtual("loading and virtualizing font %a at size %p, setting sy parameters",name,size)
end
if ss.overlay then
- local fc = fs.characters
+ local fc = fs.characters
local first = ss.first
if first then
local last = ss.last or first
@@ -904,12 +918,14 @@ function vfmath.define(specification,set,goodies)
else
local vectorname = ss.vector
if vectorname then
- local offset = 0xFF000
- local vector = mathencodings[vectorname]
- local rotcev = reverse[vectorname]
+ local offset = 0xFF000
+ local vector = mathencodings[vectorname]
+ local rotcev = reverse[vectorname]
local isextension = ss.extension
if vector and rotcev then
- local fc, fd, si = fs.characters, fs.descriptions, shared[s]
+ local fc = fs.characters
+ local fd = fs.descriptions
+ local si = shared[s]
local skewchar = ss.skewchar
for unicode, index in next, vector do
local fci = fc[index]
@@ -935,8 +951,8 @@ function vfmath.define(specification,set,goodies)
ref = { { 'slot', s, index } }
si[index] = ref
end
- local kerns = fci.kerns
- local width = fci.width
+ local kerns = fci.kerns
+ local width = fci.width
local italic = fci.italic
if italic and italic > 0 then
-- int_a^b
diff --git a/tex/context/base/mkiv/meta-fnt.lua b/tex/context/base/mkiv/meta-fnt.lua
index d2d642902..69212d08c 100644
--- a/tex/context/base/mkiv/meta-fnt.lua
+++ b/tex/context/base/mkiv/meta-fnt.lua
@@ -189,9 +189,9 @@ statistics.register("metapost font generation", function()
if total > 0 then
local time = statistics.elapsedtime(flusher)
if total > 0 then
- return format("%i glyphs, %.3f seconds runtime, %.1f glyphs/second", total, time, total/time)
+ return format("%i glyphs, %s seconds runtime, %.1f glyphs/second", total, time, total/tonumber(time))
else
- return format("%i glyphs, %.3f seconds runtime", total, time)
+ return format("%i glyphs, %s seconds runtime", total, time)
end
end
end)
@@ -200,9 +200,9 @@ statistics.register("metapost font loading",function()
if variants > 0 then
local time = statistics.elapsedtime(metapost.fonts)
if variants > 0 then
- return format("%.3f seconds, %i instances, %.3f instances/second", time, variants, variants/time)
+ return format("%s seconds, %i instances, %.3f instances/second", time, variants, variants/tonumber(time))
else
- return format("%.3f seconds, %i instances", time, variants)
+ return format("%s seconds, %i instances", time, variants)
end
end
end)
diff --git a/tex/context/base/mkiv/meta-pdf.lua b/tex/context/base/mkiv/meta-pdf.lua
index a0bf16d90..5bcd161c0 100644
--- a/tex/context/base/mkiv/meta-pdf.lua
+++ b/tex/context/base/mkiv/meta-pdf.lua
@@ -6,6 +6,9 @@ if not modules then modules = { } end modules ['meta-pdf'] = {
license = "see context related readme files"
}
+-- This module is not used in practice but we keep it around for historic
+-- reasons.
+
-- Finally we used an optimized version. The test code can be found in
-- meta-pdh.lua but since we no longer want to overload functione we use
-- more locals now. This module keeps changing as it is also a testbed.
@@ -96,16 +99,28 @@ local function flushpath(cmd)
if #m_stack_path > 0 then
local path = { }
if m_stack_concat then
- local sx, sy = m_stack_concat[1], m_stack_concat[4]
- local rx, ry = m_stack_concat[2], m_stack_concat[3]
- local tx, ty = m_stack_concat[5], m_stack_concat[6]
+ local sx = m_stack_concat[1]
+ local sy = m_stack_concat[4]
+ local rx = m_stack_concat[2]
+ local ry = m_stack_concat[3]
+ local tx = m_stack_concat[5]
+ local ty = m_stack_concat[6]
local d = (sx*sy) - (rx*ry)
for k=1,#m_stack_path do
- local v = m_stack_path[k]
- local px, py = v[1], v[2] ; v[1], v[2] = (sy*(px-tx)-ry*(py-ty))/d, (sx*(py-ty)-rx*(px-tx))/d -- mpconcat(v[1],v[2])
+ local v = m_stack_path[k]
+ local px = v[1]
+ local py = v[2]
+ v[1] = (sy*(px-tx)-ry*(py-ty))/d
+ v[2] = (sx*(py-ty)-rx*(px-tx))/d
if #v == 7 then
- local px, py = v[3], v[4] ; v[3], v[4] = (sy*(px-tx)-ry*(py-ty))/d, (sx*(py-ty)-rx*(px-tx))/d -- mpconcat(v[3],v[4])
- local px, py = v[5], v[6] ; v[5], v[6] = (sy*(px-tx)-ry*(py-ty))/d, (sx*(py-ty)-rx*(px-tx))/d -- mpconcat(v[5],v[6])
+ px = v[3]
+ py = v[4]
+ v[3] = (sy*(px-tx)-ry*(py-ty))/d
+ v[4] = (sx*(py-ty)-rx*(px-tx))/d
+ px = v[5]
+ py = v[6]
+ v[5] = (sy*(px-tx)-ry*(py-ty))/d
+ v[6] = (sx*(py-ty)-rx*(px-tx))/d
end
path[k] = concat(v," ")
end
@@ -158,7 +173,8 @@ function mps.lineto(x,y)
end
function mps.rlineto(x,y)
- local dx, dy = 0, 0
+ local dx = 0
+ local dy = 0
local topofstack = #m_stack_path
if topofstack > 0 then
local msp = m_stack_path[topofstack]
@@ -235,7 +251,8 @@ function mps.clip()
end
function mps.textext(font, scale, str) -- old parser
- local dx, dy = 0, 0
+ local dx = 0
+ local dy = 0
if #m_stack_path > 0 then
dx, dy = m_stack_path[1][1], m_stack_path[1][2]
end
@@ -330,9 +347,12 @@ handlers[50] = function() report_mptopdf("skipping special %s",50) end
--end of not supported
function mps.setrgbcolor(r,g,b) -- extra check
- r, g, b = tonumber(r), tonumber(g), tonumber(b) -- needed when we use lpeg
+ r = tonumber(r) -- needed when we use lpeg
+ g = tonumber(g) -- needed when we use lpeg
+ b = tonumber(b) -- needed when we use lpeg
if r == 0.0123 and g < 0.1 then
- g, b = round(g*10000), round(b*10000)
+ g = round(g*10000)
+ b = round(b*10000)
local s = specials[b]
local h = round(s[#s])
local handler = handlers[h]
@@ -342,7 +362,8 @@ function mps.setrgbcolor(r,g,b) -- extra check
report_mptopdf("unknown special handler %s (1)",h)
end
elseif r == 0.123 and g < 0.1 then
- g, b = round(g*1000), round(b*1000)
+ g = round(g*1000)
+ b = round(b*1000)
local s = specials[b]
local h = round(s[#s])
local handler = handlers[h]
diff --git a/tex/context/base/mkiv/mlib-lua.lua b/tex/context/base/mkiv/mlib-lua.lua
index 8074a6a4a..9b567da81 100644
--- a/tex/context/base/mkiv/mlib-lua.lua
+++ b/tex/context/base/mkiv/mlib-lua.lua
@@ -468,7 +468,6 @@ do
runs = runs + 1
local f = cache[code]
if not f then
- -- f = loadstring(f_code(code))
f = loadstring(code .. " return mp._f_()")
if f then
cache[code] = f
@@ -480,8 +479,10 @@ do
end
end
if f then
- local _buffer_, _n_ = buffer, n
- buffer, n = { }, 0
+ local _buffer_ = buffer
+ local _n_ = n
+ buffer = { }
+ n = 0
local result = f()
if result then
local t = type(result)
@@ -493,17 +494,16 @@ do
if trace then
if #result == 0 then
report_luarun("%i: no result",nesting)
--- print(debug.traceback())
else
report_luarun("%i: result: %s",nesting,result)
end
end
- buffer, n = _buffer_, _n_
+ buffer = _buffer_
+ n = _n_
nesting = nesting - 1
return result
elseif trace then
report_luarun("%i: no result",nesting)
--- print(debug.traceback())
end
buffer, n = _buffer_, _n_
else
@@ -1027,3 +1027,22 @@ do
mp.mf_path_reset = mf_path_reset mp.pathreset = mf_path_reset
end
+
+do
+
+ -- if needed we can optimize the sub (cache last split)
+
+ local utflen, utfsub = utf.len, utf.sub
+
+ local mpnumeric = aux.numeric
+ local mpquoted = aux.quoted
+
+ function mp.utflen(s)
+ mpnumeric(utflen(s))
+ end
+
+ function mp.utfsub(s,f,t)
+ mpquoted(utfsub(s,f,t or f))
+ end
+
+end
diff --git a/tex/context/base/mkiv/mlib-pdf.lua b/tex/context/base/mkiv/mlib-pdf.lua
index b90821508..92fde5e13 100644
--- a/tex/context/base/mkiv/mlib-pdf.lua
+++ b/tex/context/base/mkiv/mlib-pdf.lua
@@ -380,27 +380,30 @@ function metapost.flush(specification,result)
local figures = result.fig
if figures then
flusher = flusher or pdfflusher
- local resetplugins = metapost.resetplugins or ignore -- before figure
- local processplugins = metapost.processplugins or ignore -- each object
+ local resetplugins = metapost.resetplugins or ignore -- before figure
+ local processplugins = metapost.processplugins or ignore -- each object
local synchronizeplugins = metapost.synchronizeplugins or ignore
- local pluginactions = metapost.pluginactions or ignore -- before / after
- local startfigure = flusher.startfigure
- local stopfigure = flusher.stopfigure
- local flushfigure = flusher.flushfigure
- local textfigure = flusher.textfigure
- local processspecial = flusher.processspecial or metapost.processspecial
- metapost.comment = flusher.comment or nocomment
+ local pluginactions = metapost.pluginactions or ignore -- before / after
+ local startfigure = flusher.startfigure
+ local stopfigure = flusher.stopfigure
+ local flushfigure = flusher.flushfigure
+ local textfigure = flusher.textfigure
+ local processspecial = flusher.processspecial or metapost.processspecial
+ metapost.comment = flusher.comment or nocomment
for index=1,#figures do
- local figure = figures[index]
+ local figure = figures[index]
local properties = pushproperties(figure)
if askedfig == "direct" or askedfig == "all" or askedfig == properties.number then
- local objects = getobjects(result,figure,index)
- local result = { }
- local miterlimit, linecap, linejoin, dashed = -1, -1, -1, false
- local llx = properties.llx
- local lly = properties.lly
- local urx = properties.urx
- local ury = properties.ury
+ local objects = getobjects(result,figure,index)
+ local result = { }
+ local miterlimit = -1
+ local linecap = -1
+ local linejoin = -1
+ local dashed = false
+ local llx = properties.llx
+ local lly = properties.lly
+ local urx = properties.urx
+ local ury = properties.ury
if urx < llx then
-- invalid
startfigure(properties.number,0,0,0,0,"invalid",figure)
@@ -451,8 +454,11 @@ function metapost.flush(specification,result)
setmetatable(object, {
__index = original
})
- local before, after = processplugins(object)
- local evenodd, collect, both = false, false, false
+ local before,
+ after = processplugins(object)
+ local evenodd = false
+ local collect = false
+ local both = false
local postscript = object.postscript
if not object.istext then
if postscript == "evenodd" then
@@ -513,10 +519,11 @@ function metapost.flush(specification,result)
dashed = false
end
end
- local path = object.path -- newpath
- local transformed, penwidth = false, 1
- local open = path and path[1].left_type and path[#path].right_type -- at this moment only "end_point"
- local pen = object.pen
+ local path = object.path -- newpath
+ local transformed = false
+ local penwidth = 1
+ local open = path and path[1].left_type and path[#path].right_type -- at this moment only "end_point"
+ local pen = object.pen
if pen then
if pen.type == "elliptical" then
transformed, penwidth = pen_characteristics(original) -- boolean, value
diff --git a/tex/context/base/mkiv/mlib-pps.lua b/tex/context/base/mkiv/mlib-pps.lua
index 5ee375982..5708577fe 100644
--- a/tex/context/base/mkiv/mlib-pps.lua
+++ b/tex/context/base/mkiv/mlib-pps.lua
@@ -202,7 +202,8 @@ local function checkandconvert(ca,cb,model)
ca = { cmyktorgb(ca[1],ca[2],ca[3],ca[4]) }
cb = { cmyktorgb(cb[1],cb[2],cb[3],cb[4]) }
elseif #ca == 1 then
- local a, b = 1-ca[1], 1-cb[1]
+ local a = 1 - ca[1]
+ local b = 1 - cb[1]
ca = { a, a, a }
cb = { b, b, b }
end
@@ -334,14 +335,19 @@ function models.all(cr)
local s = cr[1]
return checked_color_pair(f_gray,s,s)
elseif n == 3 then
- local r, g, b = cr[1], cr[2], cr[3]
+ local r = cr[1]
+ local g = cr[2]
+ local b = cr[3]
if r == g and g == b then
return checked_color_pair(f_gray,r,r)
else
return checked_color_pair(f_rgb,r,g,b,r,g,b)
end
else
- local c, m, y, k = cr[1], cr[2], cr[3], cr[4]
+ local c = cr[1]
+ local m = cr[2]
+ local y = cr[3]
+ local k = cr[4]
if c == m and m == y and y == 0 then
k = 1 - k
return checked_color_pair(f_gray,k,k)
@@ -353,10 +359,15 @@ function models.all(cr)
local s = cr[1]
return checked_color_pair(f_gray,s,s)
elseif n == 3 then
- local r, g, b = cr[1], cr[2], cr[3]
+ local r = cr[1]
+ local g = cr[2]
+ local b = cr[3]
return checked_color_pair(f_rgb,r,g,b,r,g,b)
else
- local c, m, y, k = cr[1], cr[2], cr[3], cr[4]
+ local c = cr[1]
+ local m = cr[2]
+ local y = cr[3]
+ local k = cr[4]
return checked_color_pair(f_cmyk,c,m,y,k,c,m,y,k)
end
end
@@ -370,14 +381,19 @@ function models.rgb(cr)
local s = cr[1]
checked_color_pair(f_gray,s,s)
elseif n == 3 then
- local r, g, b = cr[1], cr[2], cr[3]
+ local r = cr[1]
+ local g = cr[2]
+ local b = cr[3]
if r == g and g == b then
return checked_color_pair(f_gray,r,r)
else
return checked_color_pair(f_rgb,r,g,b,r,g,b)
end
else
- local c, m, y, k = cr[1], cr[2], cr[3], cr[4]
+ local c = cr[1]
+ local m = cr[2]
+ local y = cr[3]
+ local k = cr[4]
if c == m and m == y and y == 0 then
k = 1 - k
return checked_color_pair(f_gray,k,k)
@@ -390,11 +406,12 @@ function models.rgb(cr)
local s = cr[1]
return checked_color_pair(f_gray,s,s)
else
+ local r = cr[1]
+ local g = cr[2]
+ local b = cr[3]
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]
+ r, g, b = cmyktorgb(r,g,b,cr[4])
end
return checked_color_pair(f_rgb,r,g,b,r,g,b)
end
@@ -409,7 +426,9 @@ function models.cmyk(cr)
local s = cr[1]
return checked_color_pair(f_gray,s,s)
elseif n == 3 then
- local r, g, b = cr[1], cr[2], cr[3]
+ local r = cr[1]
+ local g = cr[2]
+ local b = cr[3]
if r == g and g == b then
return checked_color_pair(f_gray,r,r)
else
@@ -417,7 +436,10 @@ function models.cmyk(cr)
return checked_color_pair(f_cmyk,c,m,y,k,c,m,y,k)
end
else
- local c, m, y, k = cr[1], cr[2], cr[3], cr[4]
+ local c = cr[1]
+ local m = cr[2]
+ local y = cr[3]
+ local k = cr[4]
if c == m and m == y and y == 0 then
k = k - 1
return checked_color_pair(f_gray,k,k)
@@ -429,18 +451,20 @@ function models.cmyk(cr)
local s = cr[1]
return checked_color_pair(f_gray,s,s)
else
- local c, m, y, k
+ local c = cr[1]
+ local m = cr[2]
+ local y = cr[3]
+ local k = cr[4]
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]
+ c, m, y, k = rgbtocmyk(c,m,y)
end
return checked_color_pair(f_cmyk,c,m,y,k,c,m,y,k)
end
end
function models.gray(cr)
- local n, s = #cr, 0
+ local n = #cr
+ local s = 0
if n == 0 then
return checked_color_pair()
elseif n == 4 then
@@ -714,11 +738,16 @@ local basepoints = number.dimenfactors["bp"]
local function cm(object)
local op = object.path
if op then
- local first, second, fourth = op[1], op[2], op[4]
+ local first = op[1]
+ local second = op[2]
+ local fourth = op[4]
if fourth then
- 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
+ local tx = first.x_coord
+ local ty = first.y_coord
+ local sx = second.x_coord - tx
+ local sy = fourth.y_coord - ty
+ local rx = second.y_coord - ty
+ local ry = fourth.x_coord - tx
if sx == 0 then sx = 0.00001 end
if sy == 0 then sy = 0.00001 end
return sx, rx, ry, sy, tx, ty
@@ -1166,10 +1195,13 @@ end
local function ps_process(object,prescript,before,after)
local ps_label = prescript.ps_label
if ps_label then
- local op = object.path
- local first, third = op[1], op[3]
- local x, y = first.x_coord, first.y_coord
- local w, h = third.x_coord - x, third.y_coord - y
+ local op = object.path
+ local first = op[1]
+ local third = op[3]
+ local x = first.x_coord
+ local y = first.y_coord
+ local w = third.x_coord - x
+ local h = third.y_coord - y
local properties = metapost.properties
x = x - properties.llx
y = properties.ury - y
@@ -1370,7 +1402,10 @@ local function gr_process(object,prescript,before,after)
elseif gr_state == "start" then
local gr_type = utilities.parsers.settings_to_set(prescript.gr_type)
local path = object.path
- local p1, p2, p3, p4 = path[1], path[2], path[3], path[4]
+ local p1 = path[1]
+ local p2 = path[2]
+ local p3 = path[3]
+ local p4 = path[4]
local llx = min(p1.x_coord,p2.x_coord,p3.x_coord,p4.x_coord)
local lly = min(p1.y_coord,p2.y_coord,p3.y_coord,p4.y_coord)
local urx = max(p1.x_coord,p2.x_coord,p3.x_coord,p4.x_coord)
diff --git a/tex/context/base/mkiv/mlib-run.lua b/tex/context/base/mkiv/mlib-run.lua
index a3a833c4e..3365e3d42 100644
--- a/tex/context/base/mkiv/mlib-run.lua
+++ b/tex/context/base/mkiv/mlib-run.lua
@@ -131,7 +131,9 @@ function metapost.reporterror(result)
if not result then
report_metapost("error: no result object returned")
elseif result.status > 0 then
- local t, e, l = result.term, result.error, result.log
+ local t = result.term
+ local e = result.error
+ local l = result.log
local report = metapost.texerrors and texerrormessage or report_metapost
if t and t ~= "" then
report("mp error: %s",striplines(t))
@@ -201,6 +203,7 @@ function metapost.load(name,method)
make_text = metapost.maketext,
extensions = 1,
-- random_seed = seed,
+ utf8_mode = true,
}
report_metapost("initializing number mode %a",method)
local result
@@ -346,6 +349,13 @@ function metapost.pushformat(specification,f,m) -- was: instance, name, method
return mpx
end
+
+-- luatex.wrapup(function()
+-- for k, mpx in next, mpxformats do
+-- mpx:finish()
+-- end
+-- end)
+
function metapost.popformat()
nofformats = nofformats - 1
end
diff --git a/tex/context/base/mkiv/mtx-context-listing.tex b/tex/context/base/mkiv/mtx-context-listing.tex
index 1053e80b9..285113850 100644
--- a/tex/context/base/mkiv/mtx-context-listing.tex
+++ b/tex/context/base/mkiv/mtx-context-listing.tex
@@ -116,10 +116,10 @@
-- forced
end
context.page()
- context.setupfootertexts( -- return true: we need to keep this entry
- { function() context.detokenize(pattern and filename or file.basename(filename)) return true end },
- { function() context.pagenumber() return true end }
- )
+-- context.setupfootertexts( -- return true: we need to keep this entry
+-- { function() context.detokenize(pattern and filename or file.basename(filename)) return true end },
+-- { function() context.pagenumber() return true end }
+-- )
if scite then
context.scitefile { filename } -- here { }
elseif pretty then
diff --git a/tex/context/base/mkiv/mult-fun.lua b/tex/context/base/mkiv/mult-fun.lua
index 0776f36b4..71d612156 100644
--- a/tex/context/base/mkiv/mult-fun.lua
+++ b/tex/context/base/mkiv/mult-fun.lua
@@ -165,6 +165,8 @@ return {
--
"inpath", "pointof", "leftof", "rightof",
--
+ "utflen", "utfsub",
+ --
"newhash", "disposehash", "inhash", "tohash",
--
"isarray", "prefix", "isobject",
diff --git a/tex/context/base/mkiv/mult-sys.mkiv b/tex/context/base/mkiv/mult-sys.mkiv
index fdb2ea732..bd8fc80ff 100644
--- a/tex/context/base/mkiv/mult-sys.mkiv
+++ b/tex/context/base/mkiv/mult-sys.mkiv
@@ -239,39 +239,41 @@
\definesystemconstant {xml}
\definesystemconstant {lua}
-\definesystemconstant {next}
-\definesystemconstant {pickup}
-\definesystemconstant {forget}
-\definesystemconstant {ascii}
-\definesystemconstant {default}
-\definesystemconstant {unknown}
\definesystemconstant {action}
+\definesystemconstant {ascii}
+\definesystemconstant {chain}
+\definesystemconstant {child}
+\definesystemconstant {class}
+\definesystemconstant {clone}
\definesystemconstant {compare}
-\definesystemconstant {do}
-\definesystemconstant {dodo}
\definesystemconstant {complex}
-\definesystemconstant {simple}
-\definesystemconstant {start}
-\definesystemconstant {stop}
-\definesystemconstant {dummy}
-\definesystemconstant {local}
-\definesystemconstant {global}
+\definesystemconstant {counter}
+\definesystemconstant {current}
+\definesystemconstant {default}
+\definesystemconstant {dodo}
\definesystemconstant {done}
+\definesystemconstant {do}
+\definesystemconstant {dummy}
\definesystemconstant {font}
+\definesystemconstant {forget}
+\definesystemconstant {global}
+\definesystemconstant {handler}
+\definesystemconstant {indeed}
+\definesystemconstant {internal}
\definesystemconstant {link}
+\definesystemconstant {local}
+\definesystemconstant {multi}
+\definesystemconstant {next}
\definesystemconstant {parent}
-\definesystemconstant {child}
-\definesystemconstant {clone}
+\definesystemconstant {pickup}
+\definesystemconstant {plural}
\definesystemconstant {section}
-\definesystemconstant {handler}
-\definesystemconstant {counter}
+\definesystemconstant {simple}
\definesystemconstant {single}
-\definesystemconstant {multi}
-\definesystemconstant {indeed}
-\definesystemconstant {internal}
-\definesystemconstant {current}
-\definesystemconstant {chain}
-\definesystemconstant {class}
+\definesystemconstant {singular}
+\definesystemconstant {start}
+\definesystemconstant {stop}
+\definesystemconstant {unknown}
% translating setups is asking for a mess so we keep them as-is:
@@ -454,6 +456,8 @@
\definesystemconstant {left}
\definesystemconstant {middle}
\definesystemconstant {right}
+\definesystemconstant {xoffset}
+\definesystemconstant {yoffset}
%D As the name of their define command states, the next set of constants is used in
%D the message macro's.
diff --git a/tex/context/base/mkiv/node-fnt.lua b/tex/context/base/mkiv/node-fnt.lua
index 154853121..01d7e42e5 100644
--- a/tex/context/base/mkiv/node-fnt.lua
+++ b/tex/context/base/mkiv/node-fnt.lua
@@ -437,6 +437,8 @@ do
local prevfont = nil
local prevattr = nil
local none = false
+ firstnone = nil
+ basefont = nil
for n, char, font in nextchar, r do
local attr = getattr(n) or 0 -- zero attribute is reserved for fonts in context
if font ~= prevfont or attr ~= prevattr then
@@ -446,6 +448,7 @@ do
if fontmode == "none" then
setnone(n)
elseif fontmode == "base" then
+ -- so the replace gets an extra treatment ... so be it
setbase(n)
else
setnode(n,font,attr)
diff --git a/tex/context/base/mkiv/node-ini.lua b/tex/context/base/mkiv/node-ini.lua
index 38d75cfb9..f910c7e01 100644
--- a/tex/context/base/mkiv/node-ini.lua
+++ b/tex/context/base/mkiv/node-ini.lua
@@ -364,7 +364,7 @@ dirvalues = allocate(swapped(dirvalues,dirvalues))
gluevalues = allocate(swapped(gluevalues,gluevalues))
literalvalues = allocate(swapped(literalvalues,literalvalues))
-if CONTEXTLMTXMODE then
+if CONTEXTLMTXMODE > 1 then
whatcodes.literal = 0x1 whatcodes[0x1] = "literal"
whatcodes.latelua = 0x2 whatcodes[0x2] = "latelua"
whatcodes.userdefined = 0x3 whatcodes[0x3] = "userdefined"
diff --git a/tex/context/base/mkiv/node-met.lua b/tex/context/base/mkiv/node-met.lua
index f5db4babd..574c71f60 100644
--- a/tex/context/base/mkiv/node-met.lua
+++ b/tex/context/base/mkiv/node-met.lua
@@ -136,103 +136,82 @@ nodes.is_zero_glue = node.is_zero_glue
nodes.tonode = function(n) return n end
nodes.tonut = function(n) return n end
-local n_getid = node.getid
-local n_getlist = node.getlist
-local n_getnext = node.getnext
-local n_getprev = node.getprev
-local n_getchar = node.getchar
-local n_getfont = node.getfont
-local n_getsubtype = node.getsubtype
-local n_getfield = node.getfield
-local n_getattr = node.get_attribute
-local n_getdisc = node.getdisc
-local n_getleader = node.getleader
-
-local n_setfield = node.setfield
-local n_setattr = n_setfield
-
-local n_setnext = node.setnext or -- always
- function(c,n)
- n_setfield(c,"next",n)
- end
-local n_setprev = node.setprev or -- always
- function(c,p)
- n_setfield(c,"prev",p)
- end
-local n_setlist = node.setlist or -- always
- function(c,l)
- n_setfield(c,"list",l)
- end
-local n_setlink = node.setlink or -- always
- function(...)
- -- not that fast but not used often anyway
- local h = nil
- for i=1,select("#",...) do
- local n = select(i,...)
- if not n then
- -- go on
- elseif h then
- n_setfield(h,"next",n)
- n_setfield(n,"prev",h)
- else
- h = n
- end
+-- These are never used in \CONTEXT, only as a gimmick in node operators
+-- so we keep them around.
+
+local n_getfield = node.getfield
+local n_getattr = node.get_attribute
+
+local n_setfield = node.setfield
+local n_setattr = n_setfield
+
+nodes.getfield = n_getfield
+nodes.setfield = n_setfield
+nodes.getattr = n_getattr
+nodes.setattr = n_setattr
+nodes.takeattr = nodes.unset_attribute
+
+local function n_getid (n) return n_getfield(n,"id") end
+local function n_getsubtype(n) return n_getfield(n,"subtype") end
+
+nodes.getid = n_getid
+nodes.getsubtype = n_getsubtype
+
+local function n_getchar(n) return n_getfield(n,"char") end
+local function n_setchar(n,c) return n_setfield(n,"char",c) end
+local function n_getfont(n) return n_getfield(n,"font") end
+local function n_setfont(n,f) return n_setfield(n,"font",f) end
+
+nodes.getchar = n_getchar
+nodes.setchar = n_setchar
+nodes.getfont = n_getfont
+nodes.setfont = n_setfont
+
+local function n_getlist (n) return n_getfield(n,"list") end
+local function n_setlist (n,l) return n_setfield(n,"list",l) end
+local function n_getleader(n) return n_getfield(n,"leader") end
+local function n_setleader(n,l) return n_setfield(n,"leader",l) end
+
+nodes.getlist = n_getlist
+nodes.setlist = n_setlist
+nodes.getleader = n_getleader
+nodes.setleader = n_setleader
+
+local function n_getnext(n) return n_getfield(n,"next") end
+local function n_setnext(n,nn) return n_setfield(n,"next",nn) end
+local function n_getprev(n) return n_getfield(n,"prev") end
+local function n_setprev(n,pp) return n_setfield(n,"prev",pp) end
+local function n_getboth(n) return n_getfield(n,"prev"), n_getfield(n,"next") end
+local function n_setboth(n,pp,nn) return n_setfield(n,"prev",pp), n_setfield(n,"next",nn) end
+
+nodes.getnext = n_getnext
+nodes.setnext = n_setnext
+nodes.getprev = n_getprev
+nodes.setprev = n_setprev
+nodes.getboth = n_getboth
+nodes.setboth = n_setboth
+
+local function n_setlink(...)
+ -- not that fast but not used often anyway
+ local h = nil
+ for i=1,select("#",...) do
+ local n = select(i,...)
+ if not n then
+ -- go on
+ elseif h then
+ n_setfield(h,"next",n)
+ n_setfield(n,"prev",h)
+ else
+ h = n
end
- return h
- end
-local n_setboth = node.setboth or -- always
- function(c,p,n)
- n_setfield(c,"prev",p)
- n_setfield(c,"next",n)
- end
-
-nodes.setnext = n_setnext
-nodes.setprev = n_setprev
-nodes.setlink = n_setlink
-nodes.setboth = n_setboth
-nodes.setlist = n_setlist
-
-nodes.getfield = n_getfield
-nodes.setfield = n_setfield
-nodes.getattr = n_getattr
-nodes.setattr = n_setattr
-nodes.takeattr = nodes.unset_attribute
-
-nodes.getnext = n_getnext
-nodes.getprev = n_getprev
-nodes.getid = n_getid
-nodes.getchar = n_getchar
-nodes.getfont = n_getfont
-nodes.getsubtype = n_getsubtype
-nodes.getlist = n_getlist
-nodes.getleader = n_getleader
-nodes.getdisc = n_getdisc
-
-if not node.getwhd then
- function node.getwhd(n)
- return n_getfield(n,"width"), n_getfield(n,"height"), n_getfield(n,"depth")
end
+ return h
end
-if not node.setwhd then
- function node.setwhd(n,w,h,d)
- n_setfield(n,"width",w or 0)
- n_setfield(n,"height",h or 0)
- n_setfield(n,"depth",d or 0)
- end
-end
-
-nodes.getwhd = node.getwhd
-nodes.setwhd = node.setwhd
-
-nodes.is_char = node.is_char
-nodes.ischar = node.is_char
-
-nodes.is_glyph = node.is_glyph
-nodes.isglyph = node.is_glyph
+nodes.setlink = n_setlink
-nodes.getbox = node.getbox or tex.getbox
-nodes.setbox = node.setbox or tex.setbox
+nodes.getbox = node.getbox or tex.getbox
+nodes.setbox = node.setbox or tex.setbox
local n_flush_node = nodes.flush
local n_copy_node = nodes.copy
diff --git a/tex/context/base/mkiv/node-nut.lua b/tex/context/base/mkiv/node-nut.lua
index 85220e25b..50e87e988 100644
--- a/tex/context/base/mkiv/node-nut.lua
+++ b/tex/context/base/mkiv/node-nut.lua
@@ -127,11 +127,11 @@ nodes.tonut = tonut
-- function nuts.reportattr()
-- inspect(hash)
-- end
---
+
-- local function track(name)
-- local n = 0
--- local f = nuts[name]
--- function nuts[name](...)
+-- local f = direct[name]
+-- direct[name] = function(...)
-- n = n + 1
-- if n % 1000 == 0 then
-- print(name,n)
@@ -139,7 +139,6 @@ nodes.tonut = tonut
-- return f(...)
-- end
-- end
---
-- track("getfield")
-- helpers
@@ -698,7 +697,7 @@ nuts.nestedtracedslide = nestedtracedslide
-- this might move
-local propertydata = direct.get_properties_table and direct.get_properties_table()
+local propertydata = direct.get_properties_table(true)
local getattr = nuts.getattr
local setattr = nuts.setattr
diff --git a/tex/context/base/mkiv/node-pro.lua b/tex/context/base/mkiv/node-pro.lua
index b6b130588..606d5b8d7 100644
--- a/tex/context/base/mkiv/node-pro.lua
+++ b/tex/context/base/mkiv/node-pro.lua
@@ -14,6 +14,7 @@ local report_nodes = logs.reporter("nodes","processors")
local nodes = nodes
local tasks = nodes.tasks
local nuts = nodes.nuts
+local tonut = nodes.tonut
nodes.processors = nodes.processors or { }
local processors = nodes.processors
@@ -25,7 +26,6 @@ local actions = tasks.actions("processors")
do
- local tonut = nuts.tonut
local isglyph = nuts.isglyph
local getnext = nuts.getnext
@@ -178,9 +178,9 @@ do
local texnest = tex.nest
- local getlist = nodes.getlist
- local setlist = nodes.setlist
- local getsubtype = nodes.getsubtype
+ local getlist = nuts.getlist
+ local setlist = nuts.setlist
+ local getsubtype = nuts.getsubtype
local linelist_code = nodes.listcodes.line
@@ -191,12 +191,15 @@ do
local whatever = texnest[texnest.ptr]
if whatever then
local line = whatever.tail
- if line and getsubtype(line) == linelist_code then
- local head = getlist(line)
- if head then
- local result = actions(head,groupcode,line)
- if result and result ~= head then
- setlist(line,result)
+ if line then
+ line = tonut(line)
+ if getsubtype(line) == linelist_code then
+ local head = getlist(line)
+ if head then
+ local result = actions(head,groupcode,line)
+ if result and result ~= head then
+ setlist(line,result)
+ end
end
end
end
diff --git a/tex/context/base/mkiv/node-ref.lua b/tex/context/base/mkiv/node-ref.lua
index 107cadc46..e12bd95bd 100644
--- a/tex/context/base/mkiv/node-ref.lua
+++ b/tex/context/base/mkiv/node-ref.lua
@@ -755,7 +755,11 @@ local function makereference(width,height,depth,reference) -- height and depth a
if trace_references then
report_reference("resolving attribute %a",reference)
end
- local resolved, ht, dp, set, n = sr[1], sr[2], sr[3], sr[4], sr[5]
+ local resolved = sr[1]
+ local ht = sr[2]
+ local dp = sr[3]
+ local set = sr[4]
+ local n = sr[5]
-- logs.report("temp","child: ht=%p dp=%p, parent: ht=%p dp=%p",ht,dp,height,depth)
if ht then
if height < ht then height = ht end
@@ -844,7 +848,11 @@ local function makedestination(width,height,depth,reference)
if trace_destinations then
report_destination("resolving attribute %a",reference)
end
- local resolved, ht, dp, name, view = sr[1], sr[2], sr[3], sr[4], sr[5] -- sr[4] will change to just internal
+ local resolved = sr[1]
+ local ht = sr[2]
+ local dp = sr[3]
+ local name = sr[4]
+ local view = sr[5]
if ht then
if height < ht then height = ht end
if depth < dp then depth = dp end
diff --git a/tex/context/base/mkiv/node-res.lua b/tex/context/base/mkiv/node-res.lua
index da8daa29b..5b4961683 100644
--- a/tex/context/base/mkiv/node-res.lua
+++ b/tex/context/base/mkiv/node-res.lua
@@ -172,7 +172,7 @@ local savepos = register_nut(new_nut(whatsit_code,whatsitcodes.savepos
local user_node = new_nut(whatsit_code,whatsitcodes.userdefined)
-if not CONTEXTLMTXMODE then
+if CONTEXTLMTXMODE < 2 then
setfield(user_node,"type",usercodes.number)
end
@@ -364,49 +364,37 @@ function nutpool.direction(dir,swap)
return t
end
-function nutpool.rule(width,height,depth,direction) -- w/h/d == nil will let them adapt
+function nutpool.rule(width,height,depth) -- w/h/d == nil will let them adapt
local n = copy_nut(rule)
if width or height or depth then
setwhd(n,width,height,depth)
end
- if direction then
- setdirection(n,direction)
- end
return n
end
-function nutpool.emptyrule(width,height,depth,direction) -- w/h/d == nil will let them adapt
+function nutpool.emptyrule(width,height,depth) -- w/h/d == nil will let them adapt
local n = copy_nut(emptyrule)
if width or height or depth then
setwhd(n,width,height,depth)
end
- if direction then
- setdirection(n,direction)
- end
return n
end
-function nutpool.userrule(width,height,depth,direction) -- w/h/d == nil will let them adapt
+function nutpool.userrule(width,height,depth) -- w/h/d == nil will let them adapt
local n = copy_nut(userrule)
if width or height or depth then
setwhd(n,width,height,depth)
end
- if direction then
- setdirection(n,direction)
- end
return n
end
-function nutpool.outlinerule(width,height,depth,line,direction) -- w/h/d == nil will let them adapt
+function nutpool.outlinerule(width,height,depth,line) -- w/h/d == nil will let them adapt
local n = copy_nut(outlinerule)
if width or height or depth then
setwhd(n,width,height,depth)
end
if line then
- setfield(n,"transform",line)
- end
- if direction then
- setdirection(n,direction)
+ if CONTEXTLMTXMODE > 1 then setdata(n,line) else setfield(n,"transform",line) end
end
return n
end
@@ -426,7 +414,7 @@ function nutpool.savepos()
return copy_nut(savepos)
end
-if CONTEXTLMTXMODE then
+if CONTEXTLMTXMODE > 1 then
function nutpool.latelua(code)
local n = copy_nut(latelua)
@@ -438,14 +426,17 @@ else
function nutpool.latelua(code)
local n = copy_nut(latelua)
+ if type(code) == "table" then
+ local action = code.action
+ local specification = code.specification or code
+ code = function() action(specification) end
+ end
setdata(n,code)
return n
end
end
-nutpool.lateluafunction = nutpool.latelua
-
function nutpool.leftmarginkern(glyph,width)
local n = copy_nut(left_margin_kern)
if not glyph then
@@ -573,7 +564,7 @@ end
local function usage()
local t = { }
for n, tag in gmatch(status.node_mem_usage,"(%d+) ([a-z_]+)") do
- t[tag] = n
+ t[tag] = tonumber(n) or 0
end
return t
end
diff --git a/tex/context/base/mkiv/node-rul.lua b/tex/context/base/mkiv/node-rul.lua
index ea0e5c7a0..1df5bf32a 100644
--- a/tex/context/base/mkiv/node-rul.lua
+++ b/tex/context/base/mkiv/node-rul.lua
@@ -48,7 +48,9 @@ local setattrlist = nuts.setattrlist
local setshift = nuts.setshift
local getwidth = nuts.getwidth
local setwidth = nuts.setwidth
+local setoffsets = nuts.setoffsets
local setfield = nuts.setfield
+local getdata = nuts.getdata
local isglyph = nuts.isglyph
@@ -163,28 +165,23 @@ local ruleactions = { }
rules .ruleactions = ruleactions
nutrules.ruleactions = ruleactions -- convenient
-local function mathradical(n,h,v)
- ----- size = getfield(n,"index")
- local font = getfield(n,"transform")
+local function mathaction(n,h,v,what)
+ local font = CONTEXTLMTXMODE > 1 and getdata(n) or getfield(n,"transform")
local actions = fontresources[font].mathruleactions
if actions then
- local action = actions.radicalaction
+ local action = actions[what]
if action then
action(n,h,v,font)
end
end
end
+local function mathradical(n,h,v)
+ mathaction(n,h,v,"radicalaction")
+end
+
local function mathrule(n,h,v)
- ----- size = getfield(n,"index")
- local font = getfield(n,"transform")
- local actions = fontresources[font].mathruleactions
- if actions then
- local action = actions.hruleaction
- if action then
- action(n,h,v,font)
- end
- end
+ mathaction(n,h,v,"hruleaction")
end
local function useraction(n,h,v)
@@ -745,7 +742,7 @@ implement {
actions = nodes.linefillers.enable
}
--- We add a bonus feature here:
+-- We add a bonus feature here (experiment):
interfaces.implement {
name = "autorule",
@@ -754,19 +751,22 @@ interfaces.implement {
{ "width", "dimension" },
{ "height", "dimension" },
{ "depth", "dimension" },
+ { "xoffset", "dimension" },
+ { "yoffset", "dimension" },
{ "left", "dimension" },
{ "right", "dimension" },
},
},
actions = function(t)
- local l = t.left
- local r = t.right
local n = new_rule(
t.width,
t.height,
t.depth
)
setattrlist(n,true)
+ setoffsets(n,t.xoffset,t.yoffset) -- ,t.left, t.right
+ local l = t.left
+ local r = t.right
if l then
setfield(n,"left",l)
end
diff --git a/tex/context/base/mkiv/node-tsk.lua b/tex/context/base/mkiv/node-tsk.lua
index 0378c14c6..ca7c7fee4 100644
--- a/tex/context/base/mkiv/node-tsk.lua
+++ b/tex/context/base/mkiv/node-tsk.lua
@@ -627,12 +627,11 @@ local tonode = nodes.nuts.tonode
%localize%
-return function(head,groupcode,line)
- local nuthead = tonut(head)
- local nutline = tonut(line)
+-- we operate exclusively on nuts
+return function(nuthead,groupcode,nutline)
%actions%
- return tonode(nuthead)
+ return nuthead
end
]],
diff --git a/tex/context/base/mkiv/pack-obj.lua b/tex/context/base/mkiv/pack-obj.lua
index 3d2048218..ea36b10de 100644
--- a/tex/context/base/mkiv/pack-obj.lua
+++ b/tex/context/base/mkiv/pack-obj.lua
@@ -53,8 +53,16 @@ end
job.register('job.objects.collected', tobesaved, initializer, nil)
local function saveobject(tag,number,page)
- local t = { number, page }
- tobesaved[tag], collected[tag] = t, t
+ local data = { number, page }
+ tobesaved[tag] = data
+ collected[tag] = data
+end
+
+local function saveobjectspec(specification)
+ local tag = specification.tag
+ local data = { specification.number, specification.page }
+ tobesaved[tag] = data
+ collected[tag] = data
end
local function setobject(tag,number,page)
@@ -162,9 +170,12 @@ function objects.restore(ns,id) -- why not just pass a box number here too (ok,
local hbox = codeinjections.restoreboxresource(index) -- a nut !
if status then
local list = getlist(hbox)
- local page = new_latelua(function()
- saveobject(ns .. "::" .. id,index,getcount("realpageno"))
- end)
+ local page = new_latelua {
+ action = saveobjectspec,
+ tag = ns .. "::" .. id,
+ number = index,
+ page = getcount("realpageno"),
+ }
setlink(list,page)
end
setbox("objectbox",hbox)
diff --git a/tex/context/base/mkiv/page-ini.mkiv b/tex/context/base/mkiv/page-ini.mkiv
index 38477dc27..618ea9006 100644
--- a/tex/context/base/mkiv/page-ini.mkiv
+++ b/tex/context/base/mkiv/page-ini.mkiv
@@ -344,6 +344,10 @@
{\clf_forcestrutdepth\normalpagebox\strutdp\c_page_force_strut_depth_trace_mode
\unvbox\normalpagebox}
+\installoutputroutine\forcestrutdepthplus % experimental
+ {\clf_forcestrutdepthplus\normalpagebox\strutdp\c_page_force_strut_depth_trace_mode
+ \unvbox\normalpagebox}
+
% maybe better:
%
% \installoutputroutine\doforcestrutdepth
diff --git a/tex/context/base/mkiv/page-lin.lua b/tex/context/base/mkiv/page-lin.lua
index b556ca32b..3689c7f8d 100644
--- a/tex/context/base/mkiv/page-lin.lua
+++ b/tex/context/base/mkiv/page-lin.lua
@@ -224,7 +224,9 @@ implement {
local function check_number(n,a,skip,sameline)
local d = data[a]
if d then
- local tag, skipflag, s = d.tag or "", 0, d.start or 1
+ local tag = d.tag or ""
+ local skipflag = 0
+ local s = d.start or 1
current_list[#current_list+1] = { n, s }
if sameline then
skipflag = 0
@@ -471,14 +473,17 @@ end
function boxed.stage_two(n,m)
if #current_list > 0 then
m = m or lines.scratchbox
- local t, tn = { }, 0
+ local t = { }
+ local tn = 0
for l in nexthlist, getlist(getbox(m)) do
tn = tn + 1
t[tn] = copy_node(l) -- use take_box instead
end
for i=1,#current_list do
local li = current_list[i]
- local n, m, ti = li[1], li[2], t[i]
+ local n = li[1]
+ local m = li[2]
+ local ti = t[i]
if ti then
-- local d = getdirection(n)
-- local l = getlist(n)
diff --git a/tex/context/base/mkiv/page-sid.mkiv b/tex/context/base/mkiv/page-sid.mkiv
index 803381244..e6c1be985 100644
--- a/tex/context/base/mkiv/page-sid.mkiv
+++ b/tex/context/base/mkiv/page-sid.mkiv
@@ -84,6 +84,8 @@
\newcount \c_page_sides_m_of_lines
\newconditional \c_page_sides_delayed
+\newconditional \c_page_sides_check_same_page
+
\newif \iftracesidefloats % public (might change)
%D Defaults:
@@ -399,10 +401,18 @@
{\iftracesidefloats
\begingroup
\c_page_force_strut_depth_trace_mode\plusone
- \forcestrutdepth
+ \ifconditional\c_page_sides_check_same_page
+ \forcestrutdepthplus
+ \else
+ \forcestrutdepth
+ \fi
\endgroup
\else
- \forcestrutdepth
+ \ifconditional\c_page_sides_check_same_page
+ \forcestrutdepthplus
+ \else
+ \forcestrutdepth
+ \fi
\fi
\page_otr_command_set_vsize} % new
@@ -712,7 +722,7 @@
\advance\d_page_sides_progress-\pagetotal
\fi}
-\def\page_sides_analyse_space
+\def\page_sides_analyse_space_stage_one
{\global\settrue\c_page_sides_flag
% \ifdim\pagegoal=\maxdimen
% \pagegoal\textheight % maybe
@@ -751,8 +761,10 @@
% \advance\scratchdimenone -\onepoint (maybe)
\else
\advance\scratchdimentwo -\strutdp
- \fi
- % how about \pagedepth
+ \fi}
+
+\def\page_sides_analyse_space_stage_two
+ {% how about \pagedepth
\ifdim\scratchdimenone>\scratchdimentwo
\global\setfalse\c_page_floats_room
\else
@@ -767,6 +779,22 @@
\global\settrue\c_page_floats_room
\fi}
+\def\page_sides_analyse_space
+ {\page_sides_analyse_space_stage_one
+ \ifconditional\c_page_sides_check_same_page
+ \ifdim\d_spac_prevcontent>\zeropoint
+ \ifdim\dimexpr\scratchdimenone+\d_spac_prevcontent>\scratchdimentwo
+ \clf_pushatsame
+ \setbox\scratchbox\vpack{\clf_popatsame}%
+ \page
+ \box\scratchbox
+ \vskip-\lineskip
+ \page_sides_analyse_space_stage_one
+ \fi
+ \fi
+ \fi
+ \page_sides_analyse_space_stage_two}
+
%D As we have no clear end of one or more paragraphs we only have pre float
%D skips.
diff --git a/tex/context/base/mkiv/publ-aut.lua b/tex/context/base/mkiv/publ-aut.lua
index fd98c5e38..e74c7ee18 100644
--- a/tex/context/base/mkiv/publ-aut.lua
+++ b/tex/context/base/mkiv/publ-aut.lua
@@ -159,8 +159,11 @@ local function splitauthor(author,justsplit)
if n == 1 then
-- {First Middle von Last}
local words = lpegmatch(spacesplitter,author)
- firstnames, vons, surnames = { }, { }, { }
- local i, n = 1, #words
+ local i = 1
+ local n = #words
+ firstnames = { }
+ vons = { }
+ surnames = { }
while i <= n do
local w = words[i]
if is_upper(w) then
@@ -198,9 +201,12 @@ local function splitauthor(author,justsplit)
elseif n == 2 then
-- {Last, First}
-- {von Last, First}
- firstnames, vons, surnames = { }, { }, { }
local words = lpegmatch(spacesplitter,split[1])
- local i, n = 1, #words
+ local i = 1
+ local n = #words
+ firstnames = { }
+ vons = { }
+ surnames = { }
while i <= n do
local w = words[i]
if is_upper(w) then
@@ -210,21 +216,25 @@ local function splitauthor(author,justsplit)
end
end
while i <= n do
- surnames[#surnames+1], i = words[i], i + 1
+ surnames[#surnames+1] = words[i]
+ i = i + 1
end
--
local words = lpegmatch(spacesplitter,split[2])
- local i, n = 1, #words
+ local i = 1
+ local n = #words
while i <= n do
local w = words[i]
if is_upper(w) then
- firstnames[#firstnames+1], i = w, i + 1
+ firstnames[#firstnames+1] = w
+ i = i + 1
else
break
end
end
while i <= n do
- vons[#vons+1], i = words[i], i + 1
+ vons[#vons+1] = words[i]
+ i = i + 1
end
if surnames and firstnames and #surnames == 0 then
-- safeguard
@@ -316,12 +326,14 @@ local function the_initials(initials,symbol,connector)
if not connector then
connector = "-"
end
- local result, r = { }, 0
+ local result = { }
+ local r = 0
for i=1,#initials do
local initial = initials[i]
if type(initial) == "table" then
-- J.-J.
- local set, s = { }, 0
+ local set = { }
+ local s = 0
for i=1,#initial do
if i > 1 then
s = s + 1 ; set[s] = connector
diff --git a/tex/context/base/mkiv/publ-imp-apa.mkvi b/tex/context/base/mkiv/publ-imp-apa.mkvi
index 160cc4522..36e4882d2 100644
--- a/tex/context/base/mkiv/publ-imp-apa.mkvi
+++ b/tex/context/base/mkiv/publ-imp-apa.mkvi
@@ -696,6 +696,30 @@
apa:Advanced={Publicación en línea avanzada},
apa:Retrieved={Obtenido de}] % {Disponible desde}]
+
+\setupbtxlabeltext
+ [sv]
+ [apa:number={nr.},
+ apa:edition={Utgåva},
+ apa:Editor=Redaktör,
+ apa:Editors=Redaktörer,
+ apa:Volume=Band,
+ apa:Volumes=Band,
+ apa:nd={u.å.}, % utan årtal
+ apa:supplement=Bilaga, % Supplement
+ apa:MotionPicture=Spelfilm, % ?
+ apa:Writer={Manusförfattare}, % Assuming for a movie
+ apa:Writers={Manusförfattare}, %
+ apa:Producer=Producent, % Assuming for a movie
+ apa:Producers=Producenter, %
+ apa:Director={Regissör}, % Assuming for a movie
+ apa:Directors={Regissörer}, %
+ apa:Recordedby={Inspelad av}, % Assuming for a movie
+ apa:Author={Författare},
+ apa:Translator={Översättare},
+ apa:Advanced={Avancerad onlinepublikation}, % ?
+ apa:Retrieved={Hämtad från}]
+
% cite setups
% The following differs from the default returning n.d. if year is empty
diff --git a/tex/context/base/mkiv/publ-imp-aps.mkvi b/tex/context/base/mkiv/publ-imp-aps.mkvi
index 4180b6491..d085b96eb 100644
--- a/tex/context/base/mkiv/publ-imp-aps.mkvi
+++ b/tex/context/base/mkiv/publ-imp-aps.mkvi
@@ -514,6 +514,20 @@
aps:tobe={que se publicará},
aps:unpublished={inédito}]
+\setupbtxlabeltext
+ [sv]
+ [aps:number={nr.},
+ aps:edition={Utgåva},
+ aps:Editor=Redaktör,
+ aps:Editors=Redaktörer,
+ aps:Volume=Band,
+ aps:Volumes=Band,
+ aps:supplement=Bilaga,
+ aps:inpress={under tryckning},
+ aps:tobe={att publiceras},
+ aps:unpublished={opublicerat}]
+
+
% cite setups
\startsetups btx:aps:nd
@@ -651,8 +665,10 @@
\stoptexdefinition
\starttexdefinition unexpanded btx:aps:author
- \btxflush{author}
- \btxcomma
+ \btxdoif {author} {
+ \btxflush{author}
+ \btxcomma
+ }
\stoptexdefinition
\starttexdefinition unexpanded btx:aps:organization-if-not-author
diff --git a/tex/context/base/mkiv/publ-imp-commands.mkvi b/tex/context/base/mkiv/publ-imp-commands.mkvi
index 14e2dbae1..281b8324a 100644
--- a/tex/context/base/mkiv/publ-imp-commands.mkvi
+++ b/tex/context/base/mkiv/publ-imp-commands.mkvi
@@ -10,6 +10,6 @@
\definebtxcommand\acro #1{\dontleavehmode{\smallcaps#1}}
\let\<<
-\let\<>
+\let\>>
\protect \endinput
diff --git a/tex/context/base/mkiv/publ-imp-default.mkvi b/tex/context/base/mkiv/publ-imp-default.mkvi
index 22638c900..fef993fe0 100644
--- a/tex/context/base/mkiv/publ-imp-default.mkvi
+++ b/tex/context/base/mkiv/publ-imp-default.mkvi
@@ -342,24 +342,36 @@
[it]
[\s!default:and=e,
\s!default:number={nº},
- \s!default:edition={ed.}, % edizione
+ \s!default:edition={ed.}, % edizione
\s!default:Editor={A cura di},
\s!default:Editors={A cura di},
- \s!default:Volume={Vol.}, % Volume
- \s!default:Volumes={Vol.}, % Volumi
+ \s!default:Volume={Vol.}, % Volume
+ \s!default:Volumes={Vol.}, % Volumi
\s!default:others={et al.}]
\setupbtxlabeltext
[es]
[\s!default:and=y,
\s!default:number={nº},
- \s!default:edition={ed.}, % edición
- \s!default:Editor=Editor, % Ed./Eds.
+ \s!default:edition={ed.}, % edición
+ \s!default:Editor=Editor, % Ed./Eds.
\s!default:Editors=Editores,
\s!default:Volume={Vol.}, % Volumen
\s!default:Volumes={Vols.}, % Volúmenes
\s!default:others={et al.}]
+\setupbtxlabeltext
+ [sv]
+ [\s!default:and=och,
+ \s!default:number={nr.},
+ \s!default:edition={Utgåva},
+ \s!default:Editor=Redaktör,
+ \s!default:Editors=Redaktörer,
+ \s!default:Volume=Band,
+ \s!default:Volumes=Band,
+ \s!default:others={et al.}]
+
+
% First some helpers:
\starttexdefinition btx:default:composed-title
diff --git a/tex/context/base/mkiv/publ-ini.lua b/tex/context/base/mkiv/publ-ini.lua
index ecc013dcd..f62352f07 100644
--- a/tex/context/base/mkiv/publ-ini.lua
+++ b/tex/context/base/mkiv/publ-ini.lua
@@ -1065,14 +1065,17 @@ do
-- maybe not redo when already done
local function shortsorter(a,b)
- local ay, by = a[2], b[2] -- year
+ local ay = a[2] -- year
+ local by = b[2] -- year
if ay ~= by then
return ay < by
end
- local ay, by = a[3], b[3] -- suffix
+ local ay = a[3] -- suffix
+ local by = b[3] -- suffix
if ay ~= by then
-- bah, bah, bah
- local an, bn = tonumber(ay), tonumber(by)
+ local an = tonumber(ay)
+ local bn = tonumber(by)
if an and bn then
return an < bn
else
@@ -2023,7 +2026,8 @@ do
for i=1,nofranges do
local r = ranges[i]
ctx_btxsetconcat(concatstate(i,nofranges))
- local first, last = r[1], r[2]
+ local first = r[1]
+ local last = r[2]
ctx_btxsetfirstinternal(first[2].internal)
ctx_btxsetfirstpage(first[1])
if last then
@@ -2044,7 +2048,8 @@ do
}
local function identical(a,b)
- local na, nb = #a, #b
+ local na = #a
+ local nb = #b
if na ~= nb then
return false
end
@@ -2056,7 +2061,8 @@ do
end
return true
end
- local ha, hb = a.hash, b.hash
+ local ha = a.hash
+ local hb = b.hash
if ha then
return ha == hb
end
diff --git a/tex/context/base/mkiv/scrn-wid.lua b/tex/context/base/mkiv/scrn-wid.lua
index 5b70bec75..17c9ebddc 100644
--- a/tex/context/base/mkiv/scrn-wid.lua
+++ b/tex/context/base/mkiv/scrn-wid.lua
@@ -143,6 +143,7 @@ implement {
{ "file" },
{ "name" },
{ "buffer" },
+ { "mimetype" },
}
}
}
@@ -172,6 +173,7 @@ implement {
{ "file" },
{ "name" },
{ "buffer" },
+ { "mimetype" },
}
}
}
diff --git a/tex/context/base/mkiv/scrn-wid.mkvi b/tex/context/base/mkiv/scrn-wid.mkvi
index d1571ca65..b92880f2e 100644
--- a/tex/context/base/mkiv/scrn-wid.mkvi
+++ b/tex/context/base/mkiv/scrn-wid.mkvi
@@ -109,6 +109,7 @@
file {\attachmentparameter\c!file}%
name {\attachmentparameter\c!name}%
buffer {\attachmentparameter\c!buffer}%
+ mimetype {\attachmentparameter\c!type}%
\relax
\endgroup
\else
@@ -211,6 +212,7 @@
file {\attachmentparameter\c!file}%
name {\attachmentparameter\c!name}%
buffer {\attachmentparameter\c!buffer}%
+ mimetype {\attachmentparameter\c!type}%
\relax
\wd\b_scrn_attachment_link\currentattachmentwidth
\ht\b_scrn_attachment_link\currentattachmentheight
@@ -228,6 +230,7 @@
file {\attachmentparameter\c!file}%
name {\attachmentparameter\c!name}%
buffer {\attachmentparameter\c!buffer}%
+ mimetype {\attachmentparameter\c!type}%
\relax}
\unexpanded\def\scrn_attachment_flush_traced
diff --git a/tex/context/base/mkiv/scrp-ini.lua b/tex/context/base/mkiv/scrp-ini.lua
index c9479cccb..e6aa5f072 100644
--- a/tex/context/base/mkiv/scrp-ini.lua
+++ b/tex/context/base/mkiv/scrp-ini.lua
@@ -468,8 +468,8 @@ function scripts.injectors.handler(head)
if not start then
return head
else
- local last_a, normal_process, lastfont, originals = nil, nil, nil, nil
- local first, last, ok = nil, nil, false
+ local last_a, normal_process, lastfont, originals, first, last
+ local ok = false
while start do
local char, id = isglyph(start)
if char then
@@ -1012,12 +1012,14 @@ do
end,
nobreakspace_before = function(head,current)
- local g, p = space_glue(current), new_penalty(10000)
+ local g = space_glue(current)
+ local p = new_penalty(10000)
head, current = insert_node_before(head,current,p)
return insert_node_before(head,current,g)
end,
nobreakspace_after = function(head,current)
- local g, p = space_glue(current), new_penalty(10000)
+ local g = space_glue(current)
+ local p = new_penalty(10000)
head, current = insert_node_after(head,current,g)
return insert_node_after(head,current,p)
end,
diff --git a/tex/context/base/mkiv/sort-ini.lua b/tex/context/base/mkiv/sort-ini.lua
index f90b70be5..0916337b1 100644
--- a/tex/context/base/mkiv/sort-ini.lua
+++ b/tex/context/base/mkiv/sort-ini.lua
@@ -401,8 +401,10 @@ local function basic(a,b) -- trace ea and eb
-- hashed (shared) entries
return 0
end
- local ea, eb = a.split, b.split
- local na, nb = #ea, #eb
+ local ea = a.split
+ local eb = b.split
+ local na = #ea
+ local nb = #eb
if na == 0 and nb == 0 then
-- simple variant (single word)
local result = 0
@@ -414,7 +416,8 @@ local function basic(a,b) -- trace ea and eb
end
end
if result == 0 then
- local la, lb = #ea.uc, #eb.uc
+ local la = #ea.uc
+ local lb = #eb.uc
if la > lb then
return 1
elseif lb > la then
@@ -429,7 +432,8 @@ local function basic(a,b) -- trace ea and eb
-- complex variant, used in register (multiple words)
local result = 0
for i=1,nb < na and nb or na do
- local eai, ebi = ea[i], eb[i]
+ local eai = ea[i]
+ local ebi = eb[i]
for j=1,#sequence do
local m = sequence[j]
result = basicsort(eai[m],ebi[m])
@@ -438,7 +442,8 @@ local function basic(a,b) -- trace ea and eb
end
end
if result == 0 then
- local la, lb = #eai.uc, #ebi.uc
+ local la = #eai.uc
+ local lb = #ebi.uc
if la > lb then
return 1
elseif lb > la then
@@ -586,8 +591,18 @@ function splitters.utf(str,checked) -- we could append m and u but this is clean
-- end
-- end
end
- local m_case, z_case, p_case, m_mapping, z_mapping, p_mapping, char, byte, n = { }, { }, { }, { }, { }, { }, { }, { }, 0
- local nm, nz, np = 0, 0, 0
+ local m_case = { }
+ local z_case = { }
+ local p_case = { }
+ local m_mapping = { }
+ local z_mapping = { }
+ local p_mapping = { }
+ local char = { }
+ local byte = { }
+ local n = 0
+ local nm = 0
+ local nz = 0
+ local np = 0
for sc in utfcharacters(str) do
local b = utfbyte(sc)
if b >= digitsoffset then
diff --git a/tex/context/base/mkiv/spac-hor.mkiv b/tex/context/base/mkiv/spac-hor.mkiv
index 32b7f06fb..24c7c7893 100644
--- a/tex/context/base/mkiv/spac-hor.mkiv
+++ b/tex/context/base/mkiv/spac-hor.mkiv
@@ -717,7 +717,7 @@
\global\s_spac_narrower_left \zeropoint
\global\s_spac_narrower_right \zeropoint
\global\s_spac_narrower_middle\zeropoint
- \edef\askednarrower{#1}
+ \edef\askednarrower{#1}%
\ifx\askednarrower\v!reverse
\ifconditional\s_spac_narrower_last_swap
\leftskip \s_spac_narrower_right_last
diff --git a/tex/context/base/mkiv/spac-prf.lua b/tex/context/base/mkiv/spac-prf.lua
index d355cc533..32582c56f 100644
--- a/tex/context/base/mkiv/spac-prf.lua
+++ b/tex/context/base/mkiv/spac-prf.lua
@@ -131,6 +131,9 @@ local function getprofile(line,step)
local margin = step / 4
local min = 0
local max = ceiling(getwidth(line)/step) + 1
+ local wd = 0
+ local ht = 0
+ local dp = 0
for i=min,max do
heights[i] = 0
@@ -139,8 +142,6 @@ local function getprofile(line,step)
-- remember p
- local wd, ht, dp = 0, 0, 0
-
local function progress()
position = width
width = position + wd
diff --git a/tex/context/base/mkiv/spac-ver.lua b/tex/context/base/mkiv/spac-ver.lua
index 07a58ae47..1410e3278 100644
--- a/tex/context/base/mkiv/spac-ver.lua
+++ b/tex/context/base/mkiv/spac-ver.lua
@@ -168,6 +168,7 @@ local nodepool = nuts.pool
local new_penalty = nodepool.penalty
local new_kern = nodepool.kern
+local new_glue = nodepool.glue
local new_rule = nodepool.rule
local nodecodes = nodes.nodecodes
@@ -877,7 +878,8 @@ end
local trace_list, tracing_info, before, after = { }, false, "", ""
local function nodes_to_string(head)
- local current, t = head, { }
+ local current = head
+ local t = { }
while current do
local id = getid(current)
local ty = nodecodes[id]
@@ -1266,17 +1268,26 @@ do
if trace then
reset_tracing(head)
end
- local current, oldhead = head, head
- local glue_order, glue_data, force_glue = 0, nil, false
- local penalty_order, penalty_data, natural_penalty, special_penalty = 0, nil, nil, nil
- local parskip, ignore_parskip, ignore_following, ignore_whitespace, keep_together = nil, false, false, false, false
- local lastsnap = nil
+ local current = head
+ local oldhead = head
+ local glue_order = 0
+ local glue_data
+ local force_glue = false
+ local penalty_order = 0
+ local penalty_data
+ local natural_penalty
+ local special_penalty
+ local parskip
+ local ignore_parskip = false
+ local ignore_following = false
+ local ignore_whitespace = false
+ local keep_together = false
+ local lastsnap
+ local pagehead
+ local pagetail
--
-- todo: keep_together: between headers
--
- local pagehead = nil
- local pagetail = nil
-
local function getpagelist()
if not pagehead then
pagehead = texlists.page_head
@@ -1952,8 +1963,9 @@ do
if stackhead then
if trace_collect_vspacing then report("%s > appending %s nodes to stack (final): %s",where,newhead) end
setlink(stacktail,newhead)
- newhead = stackhead
- stackhead, stacktail = nil, nil
+ newhead = stackhead
+ stackhead = nil
+ stacktail = nil
end
if stackhack then
stackhack = false
@@ -2146,27 +2158,105 @@ do
trackers.register("vspacing.forcestrutdepth",function(v) trace = v end)
- function vspacing.forcestrutdepth(n,depth,trace_mode)
+ local last = nil
+
+ -- function vspacing.forcestrutdepth(n,depth,trace_mode,plus)
+ -- local box = texgetbox(n)
+ -- if box then
+ -- box = tonut(box)
+ -- local head = getlist(box)
+ -- if head then
+ -- local tail = find_node_tail(head)
+ -- if tail and getid(tail) == hlist_code then
+ -- local dp = getdepth(tail)
+ -- if dp < depth then
+ -- setdepth(tail,depth)
+ -- outer.prevdepth = depth
+ -- if trace or trace_mode > 0 then
+ -- nuts.setvisual(tail,"depth")
+ -- end
+ -- end
+ -- end
+ -- end
+ -- end
+ -- end
+
+ function vspacing.forcestrutdepth(n,depth,trace_mode,plus)
local box = texgetbox(n)
if box then
box = tonut(box)
local head = getlist(box)
if head then
local tail = find_node_tail(head)
- if tail and getid(tail) == hlist_code then
- local dp = getdepth(tail)
- if dp < depth then
- setdepth(tail,depth)
- outer.prevdepth = depth
- if trace or trace_mode > 0 then
- nuts.setvisual(tail,"depth")
+ if tail then
+ if getid(tail) == hlist_code then
+ local dp = getdepth(tail)
+ if dp < depth then
+ setdepth(tail,depth)
+ outer.prevdepth = depth
+ if trace or trace_mode > 0 then
+ nuts.setvisual(tail,"depth")
+ end
+ end
+ end
+ last = nil
+ if plus then
+ -- penalty / skip ...
+ local height = 0
+ local sofar = 0
+ local same = false
+ local seen = false
+ local list = { }
+ last = nil
+ while tail do
+ local id = getid(tail)
+ if id == hlist_code or id == vlist_code then
+ local w, h, d = getwhd(tail)
+ height = height + h + d + sofar
+ sofar = 0
+ last = tail
+ elseif id == kern_code then
+ sofar = sofar + getkern(tail)
+ elseif id == glue_code then
+ if seen then
+ sofar = sofar + getwidth(tail)
+ seen = false
+ else
+ break
+ end
+ elseif id == penalty_code then
+ local p = getpenalty(tail)
+ if p >= 10000 then
+ same = true
+ seen = true
+ else
+ break
+ end
+ else
+ break
+ end
+ tail = getprev(tail)
end
+ texsetdimen("global","d_spac_prevcontent",same and height or 0)
end
end
end
end
end
+ function vspacing.pushatsame()
+ -- needs better checking !
+ if last then -- setsplit
+ nuts.setnext(getprev(last))
+ nuts.setprev(last)
+ end
+ end
+
+ function vspacing.popatsame()
+ -- needs better checking !
+ nuts.write(last)
+ end
+
end
-- interface
@@ -2194,6 +2284,25 @@ do
}
implement {
+ name = "forcestrutdepthplus",
+ arguments = { "integer", "dimension", "integer", true },
+ actions = vspacing.forcestrutdepth,
+ scope = "private"
+ }
+
+ implement {
+ name = "pushatsame",
+ actions = vspacing.pushatsame,
+ scope = "private"
+ }
+
+ implement {
+ name = "popatsame",
+ actions = vspacing.popatsame,
+ scope = "private"
+ }
+
+ implement {
name = "vspacingsetamount",
actions = vspacing.setskip,
scope = "private",
diff --git a/tex/context/base/mkiv/spac-ver.mkiv b/tex/context/base/mkiv/spac-ver.mkiv
index 7b36f9a5b..3f1be18e5 100644
--- a/tex/context/base/mkiv/spac-ver.mkiv
+++ b/tex/context/base/mkiv/spac-ver.mkiv
@@ -244,6 +244,7 @@
\newskip \s_spac_lastskip
\newdimen\d_spac_prevdepth
\newcount\c_spac_spacefactor
+\newdimen\d_spac_prevcontent % set by lua
\unexpanded\def\removelastskip
{\ifvmode\ifdim\lastskip=\zeropoint\else\vskip-\lastskip\fi\fi}
diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf
index c2c5d8791..faae4787a 100644
--- a/tex/context/base/mkiv/status-files.pdf
+++ b/tex/context/base/mkiv/status-files.pdf
Binary files differ
diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf
index b460df354..622b5fbe7 100644
--- a/tex/context/base/mkiv/status-lua.pdf
+++ b/tex/context/base/mkiv/status-lua.pdf
Binary files differ
diff --git a/tex/context/base/mkiv/strc-doc.lua b/tex/context/base/mkiv/strc-doc.lua
index 3445cbd24..4b2ac04b7 100644
--- a/tex/context/base/mkiv/strc-doc.lua
+++ b/tex/context/base/mkiv/strc-doc.lua
@@ -389,8 +389,9 @@ function sections.setentry(given)
-- new number
olddepth = newdepth
if metadata.increment then
- local oldn, newn = numbers[newdepth] or 0, 0
- local fd = forced[newdepth]
+ local oldn = numbers[newdepth] or 0
+ local newn = 0
+ local fd = forced[newdepth]
if fd then
if fd[1] == "add" then
newn = oldn + fd[2] + 1
@@ -445,7 +446,10 @@ end
function sections.reportstructure()
if sections.verbose then
- local numbers, ownnumbers, status, depth = data.numbers, data.ownnumbers, data.status, data.depth
+ local numbers = data.numbers
+ local ownnumbers = data.ownnumbers
+ local status = data.status
+ local depth = data.depth
local d = status[depth]
local o = concat(ownnumbers,".",1,depth)
local n = (numbers and concat(numbers,".",1,min(depth,#numbers))) or 0
@@ -718,7 +722,8 @@ function sections.typesetnumber(entry,kind,...) -- kind='section','number','pref
criterium = 0
end
--
- local firstprefix, lastprefix = 0, 16 -- too much, could max found level
+ local firstprefix = 0
+ local lastprefix = 16 -- too much, could max found level
if segments == v_current then
firstprefix = data.depth
lastprefix = firstprefix
@@ -741,9 +746,11 @@ function sections.typesetnumber(entry,kind,...) -- kind='section','number','pref
end
end
--
- local numbers, ownnumbers = entry.numbers, entry.ownnumbers
+ local numbers = entry.numbers
+ local ownnumbers = entry.ownnumbers
if numbers then
- local done, preceding = false, false
+ local done = false
+ local preceding = false
--
local result = kind == "direct" and { }
if result then
@@ -761,11 +768,14 @@ function sections.typesetnumber(entry,kind,...) -- kind='section','number','pref
if prefixlist and (kind == "section" or kind == "prefix" or kind == "direct") then
-- find valid set (problem: for sectionnumber we should pass the level)
-- no holes
- local b, e, bb, ee = 1, #prefixlist, 0, 0
+ local b = 1
+ local e = #prefixlist
+ local bb = 0
+ local ee = 0
-- find last valid number
for k=e,b,-1 do
local prefix = prefixlist[k]
- local index = sections.getlevel(prefix) or k
+ local index = sections.getlevel(prefix) or k
if index >= firstprefix and index <= lastprefix then
local number = numbers and numbers[index]
if number then
@@ -781,7 +791,7 @@ function sections.typesetnumber(entry,kind,...) -- kind='section','number','pref
-- find valid range
for k=b,e do
local prefix = prefixlist[k]
- local index = sections.getlevel(prefix) or k
+ local index = sections.getlevel(prefix) or k
if index >= firstprefix and index <= lastprefix then
local number = numbers and numbers[index]
if number then
diff --git a/tex/context/base/mkiv/strc-lst.lua b/tex/context/base/mkiv/strc-lst.lua
index 72c24ed5d..bc6135e72 100644
--- a/tex/context/base/mkiv/strc-lst.lua
+++ b/tex/context/base/mkiv/strc-lst.lua
@@ -99,7 +99,8 @@ local v_default = variables.default
-- for the moment not public --
local function zerostrippedconcat(t,separator)
- local f, l = 1, #t
+ local f = 1
+ local l = #t
for i=f,l do
if t[i] == 0 then
f = f + 1
@@ -309,7 +310,8 @@ local synchronizepage = function(r) -- bah ... will move
return synchronizepage(r)
end
-local function enhancelist(n)
+local function enhancelist(specification)
+ local n = specification.n
local l = cached[n]
if not l then
report_lists("enhancing %a, unknown internal",n)
@@ -851,18 +853,22 @@ end
function lists.userdata(name,r,tag) -- to tex (todo: xml)
local result = lists.result[r]
if result then
- local userdata, metadata = result.userdata, result.metadata
+ local userdata = result.userdata
local str = userdata and userdata[tag]
if str then
- return str, metadata
+ return str, result.metadata
end
end
end
function lists.uservalue(name,r,tag,default) -- to lua
local str = lists.result[r]
- str = str and str.userdata
- str = str and str[tag]
+ if str then
+ str = str.userdata
+ end
+ if str then
+ str = str[tag]
+ end
return str or default
end
@@ -1076,7 +1082,9 @@ implement {
implement {
name = "enhancelist",
arguments = "integer",
- actions = enhancelist,
+ actions = function(n)
+ enhancelist { n = n }
+ end
}
implement {
@@ -1084,7 +1092,7 @@ implement {
arguments = "integer",
protected = true, -- for now, pre 1.09
actions = function(n)
- ctx_latelua(function() enhancelist(n) end)
+ ctx_latelua { action = enhancelist, n = n }
end,
}
diff --git a/tex/context/base/mkiv/strc-mar.lua b/tex/context/base/mkiv/strc-mar.lua
index c904c699e..0221b9b8f 100644
--- a/tex/context/base/mkiv/strc-mar.lua
+++ b/tex/context/base/mkiv/strc-mar.lua
@@ -437,7 +437,8 @@ local function resolve(name,first,last,strict,quitonfalse,notrace)
if trace_marks_get and not notrace then
report_marks("found chain [ % => T ]",fullchain)
end
- local chaindata, chainlength = { }, #fullchain
+ local chaindata = { }
+ local chainlength = #fullchain
for i=1,chainlength do
local cname = fullchain[i]
if data[cname].set > 0 then
@@ -513,7 +514,8 @@ local methods = { }
local function doresolve(name,rangename,swap,df,dl,strict)
local range = ranges[rangename] or ranges[v_page]
- local first, last = range.first, range.last
+ local first = range.first
+ local last = range.last
if trace_marks_get then
report_marks("action %a, name %a, range %a, swap %a, first %a, last %a, df %a, dl %a, strict %a",
"resolving",name,rangename,swap or false,first,last,df,dl,strict or false)
@@ -642,7 +644,10 @@ function marks.tracers.showtable()
context.tabulaterowbold("name","parent","chain","children","fullchain")
context.ML()
for k, v in table.sortedpairs(data) do
- local parent, chain, children, fullchain = v.parent or "", v.chain or "", v.children or { }, v.fullchain or { }
+ local parent = v.parent or ""
+ local chain = v.chain or ""
+ local children = v.children or { }
+ local fullchain = v.fullchain or { }
table.sort(children) -- in-place but harmless
context.tabulaterowtyp(k,parent,chain,concat(children," "),concat(fullchain," "))
end
diff --git a/tex/context/base/mkiv/strc-not.lua b/tex/context/base/mkiv/strc-not.lua
index bb9d64beb..b2c8106e1 100644
--- a/tex/context/base/mkiv/strc-not.lua
+++ b/tex/context/base/mkiv/strc-not.lua
@@ -247,15 +247,38 @@ end
notes.internal = internal
notes.ordered = ordered
+-- local function onsamepageasprevious(tag)
+-- local same = false
+-- local n = getn(tag,n)
+-- local current = get(tag,n)
+-- local previous = get(tag,n-1)
+-- if current and previous then
+-- local cr = current.references
+-- local pr = previous.references
+-- same = cr and pr and cr.realpage == pr.realpage
+-- end
+-- return same and true or false
+-- end
+
local function onsamepageasprevious(tag)
- local same = false
- local n = getn(tag,n)
- local current, previous = get(tag,n), get(tag,n-1)
- if current and previous then
- local cr, pr = current.references, previous.references
- same = cr and pr and cr.realpage == pr.realpage
+ local n = getn(tag,n)
+ local current = get(tag,n)
+ if not current then
+ return false
+ end
+ local cr = current.references
+ if not cr then
+ return false
+ end
+ local previous = get(tag,n-1)
+ if not previous then
+ return false
+ end
+ local pr = previous.references
+ if not pr then
+ return false
end
- return same and true or false
+ return cr.realpage == pr.realpage
end
notes.doifonsamepageasprevious = onsamepageasprevious
@@ -471,7 +494,7 @@ local texsetglue = tex.setglue
local function check_spacing(n,i)
local gn, pn, mn = texgetglue(n)
local gi, pi, mi = texgetglue(i > 1 and "s_strc_notes_inbetween" or "s_strc_notes_before")
- local gt, pt, mt = gn+gi, pn+pi, mn+mi
+ local gt, pt, mt = gn + gi, pn + pi, mn + mi
if trace_insert then
report_insert("%s %i: %p plus %p minus %p","always ",n,gn,pn,mn)
report_insert("%s %i: %p plus %p minus %p",i > 1 and "inbetween" or "before ",n,gi,pi,mi)
diff --git a/tex/context/base/mkiv/strc-num.lua b/tex/context/base/mkiv/strc-num.lua
index e1a133f4a..25e575a56 100644
--- a/tex/context/base/mkiv/strc-num.lua
+++ b/tex/context/base/mkiv/strc-num.lua
@@ -273,7 +273,7 @@ end
function counters.compact(name,level,onlynumbers)
local cd = counterdata[name]
if cd then
- local data = cd.data
+ local data = cd.data
local compact = { }
for i=1,level or #data do
local d = data[i]
@@ -541,22 +541,26 @@ function counters.converted(name,spec) -- name can be number and reference to st
local cd
if type(name) == "number" then
cd = specials.retrieve("counter",name)
- cd = cd and cd.counter
+ if cd then
+ cd = cd.counter
+ end
else
cd = counterdata[name]
end
if cd then
- local spec = spec or { }
- local numbers, ownnumbers = { }, { }
- local reverse = spec.order == v_reverse
- local kind = spec.type or "number"
- local data = cd.data
+ local spec = spec or { }
+ local numbers = { }
+ local ownnumbers = { }
+ local reverse = spec.order == v_reverse
+ local kind = spec.type or "number"
+ local data = cd.data
for k=1,#data do
local v = data[k]
-- somewhat messy, what if subnr? only last must honour kind?
local vn
if v.own then
- numbers[k], ownnumbers[k] = v.number, v.own
+ numbers[k] = v.number
+ ownnumbers[k] = v.own
else
if kind == v_first then
vn = v.first
@@ -577,13 +581,14 @@ function counters.converted(name,spec) -- name can be number and reference to st
end
end
end
- numbers[k], ownnumbers[k] = vn or v.number, nil
+ numbers[k] = vn or v.number
+ ownnumbers[k] = nil
end
end
- cd.numbers = numbers
+ cd.numbers = numbers
cd.ownnumbers = ownnumbers
sections.typesetnumber(cd,'number',spec)
- cd.numbers = nil
+ cd.numbers = nil
cd.ownnumbers = nil
end
end
diff --git a/tex/context/base/mkiv/strc-pag.lua b/tex/context/base/mkiv/strc-pag.lua
index dcd35fc20..ee1b245b9 100644
--- a/tex/context/base/mkiv/strc-pag.lua
+++ b/tex/context/base/mkiv/strc-pag.lua
@@ -113,8 +113,9 @@ end
-- end
function pages.number(realdata,pagespec)
- local userpage, block = realdata.number, realdata.block or "" -- sections.currentblock()
- local numberspec = realdata.numberdata
+ local userpage = realdata.number
+ local block = realdata.block or "" -- sections.currentblock()
+ local numberspec = realdata.numberdata
local conversionset = (pagespec and pagespec.conversionset ~= "" and pagespec.conversionset) or (numberspec and numberspec.conversionset ~= "" and numberspec.conversionset) or ""
local conversion = (pagespec and pagespec.conversion ~= "" and pagespec.conversion ) or (numberspec and numberspec.conversion ~= "" and numberspec.conversion ) or ""
local starter = (pagespec and pagespec.starter ~= "" and pagespec.starter ) or (numberspec and numberspec.starter ~= "" and numberspec.starter ) or ""
@@ -212,9 +213,11 @@ end
function helpers.prefixlastpage(data,prefixspec,pagespec)
if data then
- local r = data.references
- local ls, lr = r.section, r.realpage
- r.section, r.realpage = r.lastsection or r.section, r.lastrealpage or r.realpage
+ local r = data.references
+ local ls = r.section
+ local lr = r.realpage
+ r.section = r.lastsection or r.section
+ r.realpage = r.lastrealpage or r.realpage
helpers.prefixpage(data,prefixspec,pagespec)
r.section, r.realpage = ls, lr
end
@@ -227,7 +230,8 @@ function helpers.analyze(entry,specification)
if not entry then
return false, false, "no entry"
end
- local yes, no = variables.yes, variables.no
+ local yes = variables.yes
+ local no = variables.no
-- section data
local references = entry.references
if not references then
diff --git a/tex/context/base/mkiv/strc-ref.lua b/tex/context/base/mkiv/strc-ref.lua
index e7ea73d3c..e01bacaac 100644
--- a/tex/context/base/mkiv/strc-ref.lua
+++ b/tex/context/base/mkiv/strc-ref.lua
@@ -434,8 +434,8 @@ end
references.synchronizepage = synchronizepage
-local function enhancereference(prefix,tag)
- local l = tobesaved[prefix][tag]
+local function enhancereference(specification)
+ local l = tobesaved[specification.prefix][specification.tag]
if l then
synchronizepage(l.references)
end
@@ -446,7 +446,9 @@ references.enhance = enhancereference
-- implement {
-- name = "enhancereference",
-- arguments = "2 strings",
--- actions = references.enhance,
+-- actions = function(prefix,tag)
+-- enhancereference { prefix = prefix, tag = tag }
+-- end,
-- }
implement {
@@ -454,7 +456,7 @@ implement {
arguments = "2 strings",
protected = true,
actions = function(prefix,tag)
- ctx_latelua(function() enhancereference(prefix,tag) end)
+ ctx_latelua { action = enhancereference, prefix = prefix, tag = tag }
end,
}
@@ -1999,7 +2001,8 @@ local function setinternalreference(specification)
local internal = specification.internal
local destination = unsetvalue
if innermethod == v_auto or innermethod == v_name then
- local t, tn = { }, 0 -- maybe add to current (now only used for tracing)
+ local t = { } -- maybe add to current (now only used for tracing)
+ local tn = 0
local reference = specification.reference
local view = specification.view
if reference then
@@ -2320,7 +2323,8 @@ genericfilters.default = genericfilters.text
function genericfilters.page(data,prefixspec,pagespec)
local pagedata = data.pagedata
if pagedata then
- local number, conversion = pagedata.number, pagedata.conversion
+ local number = pagedata.number
+ local conversion = pagedata.conversion
if not number then
-- error
elseif conversion then
diff --git a/tex/context/base/mkiv/strc-reg.lua b/tex/context/base/mkiv/strc-reg.lua
index 28f8cddcd..47ba1c533 100644
--- a/tex/context/base/mkiv/strc-reg.lua
+++ b/tex/context/base/mkiv/strc-reg.lua
@@ -568,14 +568,19 @@ local function storeregister(rawdata) -- metadata, references, entries
return #entries
end
-local function enhanceregister(name,n)
- local data = tobesaved[name].metadata.notsaved and collected[name] or tobesaved[name]
+local function enhanceregister(specification)
+ local name = specification.name
+ local n = specification.n
+ local saved = tobesaved[name]
+ local data = saved.metadata.notsaved and collected[name] or saved
local entry = data.entries[n]
if entry then
entry.references.realpage = texgetcount("realpageno")
end
end
+-- This can become extendregister(specification)!
+
local function extendregister(name,tag,rawdata) -- maybe do lastsection internally
if type(tag) == "string" then
tag = tagged[tag]
@@ -632,7 +637,9 @@ end
implement {
name = "enhanceregister",
arguments = { "string", "integer" },
- actions = enhanceregister,
+ actions = function(name,n)
+ enhanceregister { name = name, n = n } -- todo: move to scanner
+ end,
}
implement {
@@ -640,7 +647,7 @@ implement {
arguments = { "string", "integer" },
protected = true,
actions = function(name,n)
- ctx_latelua(function() enhanceregister(name,n) end)
+ ctx_latelua { action = enhanceregister, name = name, n = n }
end,
}
@@ -712,7 +719,8 @@ function registers.compare(a,b)
local ka = a.metadata.kind
local kb = b.metadata.kind
if ka == kb then
- local page_a, page_b = a.references.realpage, b.references.realpage
+ local page_a = a.references.realpage
+ local page_b = b.references.realpage
if not page_a or not page_b then
return 0
elseif page_a < page_b then
@@ -857,7 +865,9 @@ function registers.sort(data,options)
end
function registers.unique(data,options)
- local result, nofresult, prev = { }, 0, nil
+ local result = { }
+ local nofresult = 0
+ local prev = nil
local dataresult = data.result
for k=1,#dataresult do
local v = dataresult[k]
@@ -869,7 +879,8 @@ function registers.unique(data,options)
elseif pr.realpage ~= vr.realpage then
-- ok
else
- local pl, vl = pr.lastrealpage, vr.lastrealpage
+ local pl = pr.lastrealpage
+ local vl = vr.lastrealpage
if pl or vl then
if not vl then
-- ok
@@ -897,7 +908,11 @@ end
function registers.finalize(data,options) -- maps character to index (order)
local result = data.result
data.metadata.nofsorted = #result
- local split, nofsplit, lasttag, done, nofdone = { }, 0, nil, nil, 0
+ local split = { }
+ local nofsplit = 0
+ local lasttag = nil
+ local done = nil
+ local nofdone = 0
local firstofsplit = sorters.firstofsplit
for k=1,#result do
local v = result[k]
@@ -1007,7 +1022,8 @@ implement {
-- todo: ownnumber
local function pagerange(f_entry,t_entry,is_last,prefixspec,pagespec)
- local fer, ter = f_entry.references, t_entry.references
+ local fer = f_entry.references
+ local ter = t_entry.references
ctx_registerpagerange(
f_entry.metadata.name or "",
f_entry.processors and f_entry.processors[2] or "",
@@ -1040,7 +1056,8 @@ local function pagenumber(entry,prefixspec,pagespec)
end
local function packed(f_entry,t_entry)
- local fer, ter = f_entry.references, t_entry.references
+ local fer = f_entry.references
+ local ter = t_entry.references
ctx_registerpacked(
fer.internal or 0,
ter.internal or 0
@@ -1049,8 +1066,12 @@ end
local function collapsedpage(pages)
for i=2,#pages do
- local first, second = pages[i-1], pages[i]
- local first_first, first_last, second_first, second_last = first[1], first[2], second[1], second[2]
+ local first = pages[i-1]
+ local second = pages[i]
+ local first_first = first[1]
+ local first_last = first[2]
+ local second_first = second[1]
+ local second_last = second[2]
local first_last_pn = first_last .references.realpage
local second_first_pn = second_first.references.realpage
local second_last_pn = second_last .references.realpage
@@ -1146,7 +1167,8 @@ function registers.flush(data,options,prefixspec,pagespec)
done[i] = false
end
local data = sublist.data
- local d, n = 0, 0
+ local d = 0
+ local n = 0
ctx_startregistersection(sublist.tag)
for d=1,#data do
local entry = data[d]
@@ -1341,7 +1363,8 @@ function registers.flush(data,options,prefixspec,pagespec)
end
local function case_4()
- local t, nt = { }, 0
+ local t = { }
+ local nt = 0
while true do
if entry.seeword and entry.seeword.valid then
nt = nt + 1
@@ -1361,7 +1384,7 @@ function registers.flush(data,options,prefixspec,pagespec)
end
end
for i=1,nt do
- local entry = t[i]
+ local entry = t[i]
local seeword = entry.seeword
local seetext = seeword.text or ""
local processor = seeword.processor or (entry.processors and entry.processors[1]) or ""
diff --git a/tex/context/base/mkiv/strc-reg.mkiv b/tex/context/base/mkiv/strc-reg.mkiv
index 559e1bd42..1ab7d8ae0 100644
--- a/tex/context/base/mkiv/strc-reg.mkiv
+++ b/tex/context/base/mkiv/strc-reg.mkiv
@@ -939,6 +939,18 @@
\fi
\popcurrentregister}
+\newconditional\c_strc_registers_following
+
+\appendtoks
+ \edef\p_compress{\registerparameter\c!compress}%
+ \ifx\p_compress\v!text
+ \settrue\c_strc_registers_following
+ \letregisterparameter\c!compress\v!yes
+ \else
+ \setfalse\c_strc_registers_following
+ \fi
+\to \everyplaceregister
+
\unexpanded\def\registerpagerange#1#2#3#4#5#6#7#8% #1:class #2:processor content, content todo: -- configurable
{\pushcurrentregister{#1}%
\edef\p_pagenumber{\registerparameter\c!pagenumber}%
@@ -949,9 +961,17 @@
\dostarttagged\t!registerfrompage\empty
\withregisterpagecommand{#2}{#3}{#4}{#5}%
\dostoptagged
- \registeronepagerangeseparator
- \dostarttagged\t!registertopage\empty
- \withregisterpagecommand{#2}{#6}{#7}{#8}%
+ \ifconditional\c_strc_registers_following
+ \ifnum#3=\numexpr#6-1\relax
+ \labeltext{following:\s!singular}%
+ \else
+ \labeltext{following:\s!plural}%
+ \fi
+ \else
+ \registeronepagerangeseparator
+ \dostarttagged\t!registertopage\empty
+ \withregisterpagecommand{#2}{#6}{#7}{#8}%
+ \fi
\dostoptagged
\dostoptagged
\fi
diff --git a/tex/context/base/mkiv/strc-ren.mkiv b/tex/context/base/mkiv/strc-ren.mkiv
index 01464ad86..5cdf5f4a7 100644
--- a/tex/context/base/mkiv/strc-ren.mkiv
+++ b/tex/context/base/mkiv/strc-ren.mkiv
@@ -376,10 +376,12 @@
\egroup
\ifconditional\headisdisplay
\useindentnextparameter\headparameter
+ \else\ifconditional\headissomewhere
+ \ignoreparskip
+ \noindentation
\else
\ignoreparskip
- \noindentation % recently added, was a bug
- \fi}
+ \fi\fi}
% nice testcase
%
diff --git a/tex/context/base/mkiv/supp-box.lua b/tex/context/base/mkiv/supp-box.lua
index a22eb8f69..1f31f7681 100644
--- a/tex/context/base/mkiv/supp-box.lua
+++ b/tex/context/base/mkiv/supp-box.lua
@@ -365,7 +365,9 @@ implement {
}
local function getnaturaldimensions(n)
- local w, h, d = 0, 0, 0
+ local w = 0
+ local h = 0
+ local d = 0
local l = getlist(getbox(n))
if l then
w, h, d = getdimensions(l)
@@ -395,7 +397,9 @@ interfaces.implement {
name = "getnaturalwd",
arguments = "integer",
actions = function(n)
- local w, h, d = 0, 0, 0
+ local w = 0
+ local h = 0
+ local d = 0
local l = getlist(getbox(n))
if l then
w, h, d = getdimensions(l)
diff --git a/tex/context/base/mkiv/symb-ini.mkiv b/tex/context/base/mkiv/symb-ini.mkiv
index abf857675..428fcd381 100644
--- a/tex/context/base/mkiv/symb-ini.mkiv
+++ b/tex/context/base/mkiv/symb-ini.mkiv
@@ -44,9 +44,23 @@
%D \stoptyping
\installcorenamespace{symbol}
+\installcorenamespace{symbols}
\installcorenamespace{symbolset}
\installcorenamespace{symboldefault}
+%D For now we only have one option.
+
+\installparameterhandler\??symbols {symbols}
+\installsetuphandler \??symbols {symbols}
+
+\appendtoks
+ \doifelse{\symbolsparameter\c!stylealternative}\v!math
+ \settrue\setfalse\prefermathovertextchar
+\to \everysetupsymbols
+
+\setupsymbols
+ [\c!stylealternative=\v!text]
+
\let\currentsymbol \empty
\let\currentsymbolset\empty
diff --git a/tex/context/base/mkiv/syst-ini.mkiv b/tex/context/base/mkiv/syst-ini.mkiv
index 7690af018..7ce48c79f 100644
--- a/tex/context/base/mkiv/syst-ini.mkiv
+++ b/tex/context/base/mkiv/syst-ini.mkiv
@@ -1100,6 +1100,7 @@
\suppressmathparerror \plusone
\suppressifcsnameerror\plusone
+\let \suppresslongerror \relax
\newcount\suppresslongerror \let\normalsuppresslongerror \suppresslongerror
\let \suppressoutererror \suppresslongerror \let\normalsuppressoutererror \suppresslongerror
\let \suppressmathparerror \suppresslongerror \let\normalsuppressmathparerror \suppresslongerror
diff --git a/tex/context/base/mkiv/tabl-tbl.mkiv b/tex/context/base/mkiv/tabl-tbl.mkiv
index 75839caed..f3c2e2e10 100644
--- a/tex/context/base/mkiv/tabl-tbl.mkiv
+++ b/tex/context/base/mkiv/tabl-tbl.mkiv
@@ -1670,9 +1670,9 @@
\def\tabl_tabulate_hrule_inject_normal
{\autorule
- \s!height .5\d_tabl_tabulate_hrulethickness_local
- \s!depth .5\d_tabl_tabulate_hrulethickness_local
- \s!left \d_tabl_tabulate_indent
+ \s!height.5\d_tabl_tabulate_hrulethickness_local
+ \s!depth .5\d_tabl_tabulate_hrulethickness_local
+ \s!left \d_tabl_tabulate_indent
\relax}
\def\tabl_tabulate_hrule_inject_colored
diff --git a/tex/context/base/mkiv/tabl-xtb.lua b/tex/context/base/mkiv/tabl-xtb.lua
index d87a5f49e..c9d50638e 100644
--- a/tex/context/base/mkiv/tabl-xtb.lua
+++ b/tex/context/base/mkiv/tabl-xtb.lua
@@ -377,7 +377,8 @@ function xtables.set_reflow_width()
--
drc.dimensionstate = dimensionstate
--
- local nx, ny = drc.nx, drc.ny
+ local nx = drc.nx
+ local ny = drc.ny
if nx > 1 or ny > 1 then
-- local spans = data.spans -- not used
local self = true
diff --git a/tex/context/base/mkiv/toks-ini.lua b/tex/context/base/mkiv/toks-ini.lua
index 43e2d80a3..2c85a5754 100644
--- a/tex/context/base/mkiv/toks-ini.lua
+++ b/tex/context/base/mkiv/toks-ini.lua
@@ -33,6 +33,7 @@ end
local scan_toks = token.scan_toks
local scan_string = token.scan_string
local scan_argument = token.scan_argument
+local scan_tokenlist = token.scan_tokenlist
local scan_int = token.scan_int
local scan_code = token.scan_code
local scan_dimen = token.scan_dimen
@@ -208,6 +209,10 @@ if not scan_csname then
end
+local function scan_verbatim()
+ return scan_argument(false)
+end
+
tokens.scanners = { -- these expand
token = scan_token,
toks = scan_toks,
@@ -222,6 +227,8 @@ tokens.scanners = { -- these expand
count = scan_int,
string = scan_string,
argument = scan_argument,
+ tokenlist = scan_tokenlist,
+ verbatim = scan_verbatim,
code = scan_code,
word = scan_word,
number = scan_number,
diff --git a/tex/context/base/mkiv/toks-scn.lua b/tex/context/base/mkiv/toks-scn.lua
index f73ecc86c..297ef7121 100644
--- a/tex/context/base/mkiv/toks-scn.lua
+++ b/tex/context/base/mkiv/toks-scn.lua
@@ -22,6 +22,8 @@ local tokenbits = tokens.bits
local scanstring = scanners.string
local scanargument = scanners.argument
+local scanverbatim = scanners.verbatim
+local scantokenlist = scanners.tokenlist
local scaninteger = scanners.integer
local scannumber = scanners.number
local scankeyword = scanners.keyword
@@ -149,6 +151,9 @@ local shortcuts = {
close = close,
scanners = scanners,
scanstring = scanstring,
+ scanargument = scanargument,
+ scanverbatim = scanverbatim,
+ scantokenlist = scantokenlist,
scaninteger = scaninteger,
scannumber = scannumber,
scantable = scantable,
diff --git a/tex/context/base/mkiv/trac-deb.lua b/tex/context/base/mkiv/trac-deb.lua
index 95f3052fe..9788e72a0 100644
--- a/tex/context/base/mkiv/trac-deb.lua
+++ b/tex/context/base/mkiv/trac-deb.lua
@@ -31,6 +31,7 @@ local strings = tracers.strings
local texgetdimen = tex.getdimen
local texgettoks = tex.gettoks
local texgetcount = tex.getcount
+local texgethelp = tex.gethelptext or function() end
local implement = interfaces.implement
@@ -183,7 +184,7 @@ local function processerror(offset)
local linenumber = tonumber(status.linenumber) or 0
local lastcontext = status.lasterrorcontext
local lasttexerror = status.lasterrorstring or "?"
- local lastluaerror = status.lastluaerrorstring or lasttexerror
+ local lastluaerror = status.lastluaerrorstring or "?" -- lasttexerror
local luaerrorline = match(lastluaerror,[[lua%]?:.-(%d+)]]) or (lastluaerror and find(lastluaerror,"?:0:",1,true) and 0)
local lastmpserror = match(lasttexerror,[[^.-mp%serror:%s*(.*)$]])
resetmessages()
@@ -194,58 +195,83 @@ local function processerror(offset)
offset = tonumber(offset) or 10,
lasttexerror = lasttexerror,
lastmpserror = lastmpserror,
- lastluaerror = lastluaerror,
+ lastluaerror = lastluaerror, -- can be the same as lasttexerror
luaerrorline = luaerrorline,
lastcontext = lastcontext,
+ lasttexhelp = texgethelp(),
}
end
-- so one can overload the printer if (really) needed
+local quitonerror = true
+
+directives.register("system.quitonerror",function(v) quitonerror = toboolean(v) end)
+
+local busy = false
+
function tracers.printerror(specification)
- local filename = specification.filename
- local linenumber = specification.linenumber
- local lasttexerror = specification.lasttexerror
- local lastmpserror = specification.lastmpserror
- local lastluaerror = specification.lastluaerror
- local lastcontext = specification.lasterrorcontext
- local luaerrorline = specification.luaerrorline
- local errortype = specification.errortype
- local offset = specification.offset
- local report = errorreporter(luaerrorline)
- if not filename then
- report("error not related to input file: %s ...",lasttexerror)
- elseif type(filename) == "number" then
- report("error on line %s of filehandle %s: %s ...",linenumber,lasttexerror)
- else
- report_nl()
- if luaerrorline then
- if linenumber == 0 or not filename or filename == "" then
- print("\nfatal lua error:\n\n",lastluaerror,"\n")
- os.exit(1)
- return
+ if not busy then
+ busy = true
+ local filename = specification.filename
+ local linenumber = specification.linenumber
+ local lasttexerror = specification.lasttexerror
+ local lastmpserror = specification.lastmpserror
+ local lastluaerror = specification.lastluaerror
+ local lastcontext = specification.lasterrorcontext
+ local luaerrorline = specification.luaerrorline
+ local errortype = specification.errortype
+ local offset = specification.offset
+ local report = errorreporter(luaerrorline)
+ if not filename then
+ report("error not related to input file: %s ...",lasttexerror)
+ elseif type(filename) == "number" then
+ report("error on line %s of filehandle %s: %s ...",linenumber,lasttexerror)
+ else
+ report_nl()
+ if luaerrorline then
+ if linenumber == 0 or not filename or filename == "" then
+ print("\nfatal lua error:\n\n",lastluaerror,"\n")
+ luatex.abort()
+ return
+ else
+ report("lua error on line %s in file %s:\n\n%s",linenumber,filename,lastluaerror)
+ end
+ elseif lastmpserror then
+ report("mp error on line %s in file %s:\n\n%s",linenumber,filename,lastmpserror)
else
- report("lua error on line %s in file %s:\n\n%s",linenumber,filename,lastluaerror)
+ report("tex error on line %s in file %s: %s",linenumber,filename,lasttexerror)
+ if lastcontext then
+ report_nl()
+ report_str(lastcontext)
+ report_nl()
+ elseif tex.show_context then
+ report_nl()
+ tex.show_context()
+ end
end
- elseif lastmpserror then
- report("mp error on line %s in file %s:\n\n%s",linenumber,filename,lastmpserror)
- else
- report("tex error on line %s in file %s: %s",linenumber,filename,lasttexerror)
- if lastcontext then
+ report_nl()
+ report_str(tracers.showlines(filename,linenumber,offset,tonumber(luaerrorline)))
+ report_nl()
+ end
+ local errname = file.addsuffix(tex.jobname .. "-error","log")
+ if quitonerror then
+ table.save(errname,specification)
+ local help = specification.lasttexhelp
+ if help and #help > 0 then
report_nl()
- report_str(lastcontext)
+ report_str(help)
report_nl()
- elseif tex.show_context then
report_nl()
- tex.show_context()
end
+ luatex.abort()
end
- report_nl()
- report_str(tracers.showlines(filename,linenumber,offset,tonumber(luaerrorline)))
- report_nl()
+ busy = false
end
end
+luatex.wrapup(function() os.remove(file.addsuffix(tex.jobname .. "-error","log")) end)
+
local function processwarning(offset)
-- local inputstack = resolvers.inputstack
-- local filename = inputstack[#inputstack] or status.filename
@@ -324,6 +350,7 @@ function lmx.showerror(lmxname)
else
lmx.show(lmxname or 'context-error.lmx',variables)
end
+ luatex.abort()
end
function lmx.overloaderror()
diff --git a/tex/context/base/mkiv/trac-exp.lua b/tex/context/base/mkiv/trac-exp.lua
index 5879f1b7b..e25110999 100644
--- a/tex/context/base/mkiv/trac-exp.lua
+++ b/tex/context/base/mkiv/trac-exp.lua
@@ -64,7 +64,7 @@ function exporters.man(specification,...)
end
--
result[#result+1] = formatters['.TH "%s" "1" "%s" "version %s" "%s"'](name,os.date("01-01-%Y"),version,detail)
- result[#result+1] = formatters[".SH NAME\n.B %s"](name)
+ result[#result+1] = formatters[".SH NAME\n %s - %s"](name,detail) -- KB/TL wants 'detail' in this line too
result[#result+1] = formatters[".SH SYNOPSIS\n.B %s [\n.I OPTIONS ...\n.B ] [\n.I FILENAMES\n.B ]"](runner)
result[#result+1] = formatters[".SH DESCRIPTION\n.B %s"](detail)
--
diff --git a/tex/context/base/mkiv/trac-inf.lua b/tex/context/base/mkiv/trac-inf.lua
index 7a5c35fd5..a7823c251 100644
--- a/tex/context/base/mkiv/trac-inf.lua
+++ b/tex/context/base/mkiv/trac-inf.lua
@@ -214,13 +214,11 @@ function statistics.show()
-- collectgarbage("collect")
register("lua properties",function()
local hashchar = tonumber(status.luatex_hashchars)
- local hashtype = status.luatex_hashtype
local mask = lua.mask or "ascii"
- return format("engine: %s %s, used memory: %s, hash type: %s, hash chars: min(%i,40), symbol mask: %s (%s)",
+ return format("engine: %s %s, used memory: %s, hash chars: min(%i,40), symbol mask: %s (%s)",
jit and "luajit" or "lua",
LUAVERSION,
statistics.memused(),
- hashtype or "default",
hashchar and 2^hashchar or "unknown",
mask,
mask == "utf" and "τεχ" or "tex")
diff --git a/tex/context/base/mkiv/trac-lmx.lua b/tex/context/base/mkiv/trac-lmx.lua
index c7f949618..a531a76d6 100644
--- a/tex/context/base/mkiv/trac-lmx.lua
+++ b/tex/context/base/mkiv/trac-lmx.lua
@@ -684,8 +684,9 @@ end
lmx.make = lmxmake
function lmx.show(name,variables)
+ -- todo: pcall
local htmfile = lmxmake(name,variables)
- lmx.popupfile(htmfile)
+ -- lmx.popupfile(htmfile)
return htmfile
end
diff --git a/tex/context/base/mkiv/trac-log.lua b/tex/context/base/mkiv/trac-log.lua
index 206af5668..e76c9f684 100644
--- a/tex/context/base/mkiv/trac-log.lua
+++ b/tex/context/base/mkiv/trac-log.lua
@@ -114,7 +114,7 @@ local direct, subdirect, writer, pushtarget, poptarget, setlogfile, settimedlog,
-- we don't want this overhead for single messages (not that there are that
-- many; we could have a special weak table)
-if runningtex then
+if runningtex and texio then
if texio.setescape then
texio.setescape(0) -- or (false)
diff --git a/tex/context/base/mkiv/trac-vis.lua b/tex/context/base/mkiv/trac-vis.lua
index b61dadb51..4dc3bd03b 100644
--- a/tex/context/base/mkiv/trac-vis.lua
+++ b/tex/context/base/mkiv/trac-vis.lua
@@ -1210,6 +1210,7 @@ do
prev_trace_fontkern = trace_fontkern
prev_trace_italic = trace_italic
prev_trace_expansion = trace_expansion
+ attr = a
if a == unsetvalue then
trace_hbox = false
trace_vbox = false
@@ -1231,6 +1232,7 @@ do
trace_line = false
trace_space = false
trace_depth = false
+ goto list
else -- dead slow:
-- cache[a]()
trace_hbox = band(a, 1) ~= 0
@@ -1254,7 +1256,8 @@ do
trace_space = band(a,262144) ~= 0
trace_depth = band(a,524288) ~= 0
end
- attr = a
+ elseif a == unsetvalue then
+ goto list
end
if trace_strut then
setattr(current,a_layer,l_strut)
@@ -1313,7 +1316,24 @@ do
if trace_penalty then
head, current = ruledpenalty(head,current,vertical)
end
- elseif id == hlist_code then
+ elseif id == hlist_code or id == vlist_code then
+ goto list
+ elseif id == whatsit_code then
+ if trace_whatsit then
+ head, current = whatsit(head,current)
+ end
+ elseif id == user_code then
+ if trace_user then
+ head, current = user(head,current)
+ end
+ elseif id == math_code then
+ if trace_math then
+ head, current = math(head,current)
+ end
+ end
+ goto next
+ ::list::
+ if id == hlist_code then
local content = getlist(current)
if content then
setlist(current,visualize(content,false,nil,current))
@@ -1336,19 +1356,8 @@ do
elseif trace_vbox then
head, current = ruledbox(head,current,true,l_vbox,"__V",trace_simple,previous,trace_origin,parent)
end
- elseif id == whatsit_code then
- if trace_whatsit then
- head, current = whatsit(head,current)
- end
- elseif id == user_code then
- if trace_user then
- head, current = user(head,current)
- end
- elseif id == math_code then
- if trace_math then
- head, current = math(head,current)
- end
end
+ ::next::
previous = current
current = getnext(current)
end
diff --git a/tex/context/base/mkiv/typo-brk.lua b/tex/context/base/mkiv/typo-brk.lua
index 76e50ce18..d670c5319 100644
--- a/tex/context/base/mkiv/typo-brk.lua
+++ b/tex/context/base/mkiv/typo-brk.lua
@@ -265,7 +265,7 @@ function breakpoints.handler(head)
-- for now we collect but when found ok we can move the handler here
-- although it saves nothing in terms of performance
local lang = getlang(current)
- local smap = lang and lang >= 0 and lang < 0x7FFF and (cmap[numbers[lang]] or cmap[""])
+ local smap = lang and lang >= 0 and lang < 0x7FFF and (cmap[languages.numbers[lang]] or cmap[""])
if smap then
local skip = smap.skip
local start = current
@@ -314,17 +314,17 @@ function breakpoints.handler(head)
return head
end
-- we have hits
- local numbers = languages.numbers
+ -- local numbers = languages.numbers
for i=1,#done do
local data = done[i]
local start = data[1]
local stop = data[2]
local cmap = data[3]
local smap = data[4]
--- -- we do a sanity check for language
--- local lang = getlang(start)
--- local smap = lang and lang >= 0 and lang < 0x7FFF and (cmap[numbers[lang]] or cmap[""])
--- if smap then
+ -- we do a sanity check for language
+ -- local lang = getlang(start)
+ -- local smap = lang and lang >= 0 and lang < 0x7FFF and (cmap[numbers[lang]] or cmap[""])
+ -- if smap then
local nleft = smap.nleft
local cleft = 0
local prev = getprev(start)
@@ -392,7 +392,7 @@ function breakpoints.handler(head)
head, start = method(head,start,stop,smap,kern)
end
end
--- end
+ -- end
end
end
return head
diff --git a/tex/context/base/mkiv/typo-lin.lua b/tex/context/base/mkiv/typo-lin.lua
index 3b0de080d..758d0d502 100644
--- a/tex/context/base/mkiv/typo-lin.lua
+++ b/tex/context/base/mkiv/typo-lin.lua
@@ -408,12 +408,16 @@ function paragraphs.moveinline(n,blob,dx,dy)
end
end
-local lateluafunction = nodepool.lateluafunction
-local setposition = job.positions.set
-local t_anchor = { x = true, c = true }
+local latelua = nodepool.latelua
+local setposition = jobpositions.setspec
local function setanchor(h_anchor)
- return lateluafunction(function() setposition("md:h",h_anchor,t_anchor) end)
+ return latelua {
+ action = setposition,
+ name = "md:h",
+ index = h_anchor,
+ value = { x = true, c = true },
+ }
end
function paragraphs.calculatedelta(n,width,delta,atleft,islocal,followshape,area)
diff --git a/tex/context/base/mkiv/typo-mar.lua b/tex/context/base/mkiv/typo-mar.lua
index 19507f7f5..7e69162a9 100644
--- a/tex/context/base/mkiv/typo-mar.lua
+++ b/tex/context/base/mkiv/typo-mar.lua
@@ -59,8 +59,6 @@ local v_paragraph = variables.paragraph
local v_line = variables.line
local nuts = nodes.nuts
-local nodepool = nuts.pool
-
local tonode = nuts.tonode
local hpack_nodes = nuts.hpack
@@ -82,7 +80,6 @@ local setshift = nuts.setshift
local getwidth = nuts.getwidth
local setwidth = nuts.setwidth
local getheight = nuts.getheight
-local getprop = nuts.getprop
local setattrlist = nuts.setattrlist
@@ -103,10 +100,9 @@ local userdefined_code = whatsitcodes.userdefined
local nodepool = nuts.pool
-local new_usernode = nodepool.usernode
local new_hlist = nodepool.hlist
-
-local lateluafunction = nodepool.lateluafunction
+local new_usernode = nodepool.usernode
+local latelua = nodepool.latelua
local texgetdimen = tex.getdimen
local texgetcount = tex.getcount
@@ -204,7 +200,6 @@ end
function margins.save(t)
setmetatable(t,defaults)
local content = takebox(t.number)
- setprop(content,"specialcontent","margindata")
local location = t.location
local category = t.category
local inline = t.inline
@@ -220,6 +215,7 @@ function margins.save(t)
report_margindata("ignoring empty margin data %a",location or "unknown")
return
end
+ setprop(content,"specialcontent","margindata")
local store
if inline then
store = inlinestore
@@ -450,25 +446,29 @@ end
-- anchors are only set for lines that have a note
-local function sa(tag) -- maybe l/r keys ipv left/right keys
- local p = cache[tag]
+local function sa(specification) -- maybe l/r keys ipv left/right keys
+ local tag = specification.tag
+ local p = cache[tag]
if p then
if trace_marginstack then
report_margindata("updating anchor %a",tag)
end
p.p = true
p.y = true
- setposition('md:v',tag,p)
+ -- maybe settobesaved first
+ setposition("md:v",tag,p)
cache[tag] = nil -- do this later, per page a cleanup
end
end
local function setanchor(v_anchor) -- freezes the global here
- return lateluafunction(function() sa(v_anchor) end)
+ return latelua { action = sa, tag = v_anchor }
end
-local function aa(tag,n) -- maybe l/r keys ipv left/right keys
- local p = jobpositions.gettobesaved('md:v',tag)
+local function aa(specification) -- maybe l/r keys ipv left/right keys
+ local tag = specification.tag
+ local n = specification.n
+ local p = jobpositions.gettobesaved('md:v',tag)
if p then
if trace_marginstack then
report_margindata("updating injected %a",tag)
@@ -485,7 +485,7 @@ local function aa(tag,n) -- maybe l/r keys ipv left/right keys
end
local function addtoanchor(v_anchor,n) -- freezes the global here
- return lateluafunction(function() aa(v_anchor,n) end)
+ return latelua { action = aa, tag = v_anchor, n = n }
end
local function markovershoot(current) -- todo: alleen als offset > line
@@ -589,7 +589,7 @@ local function inject(parent,head,candidate)
elseif previous == current then
firstonstack = false
elseif ap and ac and ap.p == ac.p then
- local distance = ap.y - ac.y
+ local distance = (ap.y or 0) - (ac.y or 0)
if trace_margindata then
report_margindata("distance %p",distance)
end
@@ -680,7 +680,7 @@ local function inject(parent,head,candidate)
setwidth(box,0) -- not needed when wrapped
--
if isstacked then
- setlink(box,addtoanchor(v_anchor,nofinjected))
+ setlink(box,addtoanchor(v_anchors,nofinjected))
box = new_hlist(box)
-- set height / depth ?
end
@@ -733,7 +733,7 @@ local function flushinline(parent,head)
-- for now we also check for inline+yes/continue, maybe someday no such check
-- will happen; we can assume most inlines are one line heigh; also this
-- together feature can become optional
- registertogether(tonode(parent),room) -- !! tonode
+ registertogether(parent,room)
end
end
end
@@ -768,7 +768,7 @@ local function flushed(scope,parent) -- current is hlist
continue = continue or con
nofstored = nofstored - 1
if room then
- registertogether(tonode(parent),room) -- !! tonode
+ registertogether(parent,room)
end
else
break
diff --git a/tex/context/base/mkiv/util-deb.lua b/tex/context/base/mkiv/util-deb.lua
index 6932e8804..bd94b6d01 100644
--- a/tex/context/base/mkiv/util-deb.lua
+++ b/tex/context/base/mkiv/util-deb.lua
@@ -30,7 +30,15 @@ local names = { }
local initialize = false
-if not (FFISUPPORTED and ffi) then
+if lua.getpreciseticks then
+
+ initialize = function()
+ ticks = lua.getpreciseticks
+ seconds = lua.getpreciseseconds
+ initialize = false
+ end
+
+elseif not (FFISUPPORTED and ffi) then
-- we have no precise timer
diff --git a/tex/context/base/mkiv/util-env.lua b/tex/context/base/mkiv/util-env.lua
index cadfb7ac5..dde765874 100644
--- a/tex/context/base/mkiv/util-env.lua
+++ b/tex/context/base/mkiv/util-env.lua
@@ -150,8 +150,11 @@ environment.sortedflags = nil
-- context specific arguments (in order not to confuse the engine)
function environment.initializearguments(arg)
- local arguments, files = { }, { }
- environment.arguments, environment.files, environment.sortedflags = arguments, files, nil
+ local arguments = { }
+ local files = { }
+ environment.arguments = arguments
+ environment.files = files
+ environment.sortedflags = nil
for index=1,#arg do
local argument = arg[index]
if index > 0 then
@@ -170,6 +173,11 @@ function environment.initializearguments(arg)
end
end
end
+ if not environment.ownname then
+ if os.selfpath and os.selfname then
+ environment.ownname = file.addsuffix(file.join(os.selfpath,os.selfname),"lua")
+ end
+ end
environment.ownname = file.reslash(environment.ownname or arg[0] or 'unknown.lua')
end
diff --git a/tex/context/base/mkiv/util-fil.lua b/tex/context/base/mkiv/util-fil.lua
index 9f96a01b9..79af27743 100644
--- a/tex/context/base/mkiv/util-fil.lua
+++ b/tex/context/base/mkiv/util-fil.lua
@@ -14,10 +14,14 @@ local char = string.char
-- flac files). In Lua 5.3 we can probably do this better. Some code will move
-- here.
+-- We could comment those that are in fio and sio.
+
utilities = utilities or { }
local files = { }
utilities.files = files
+-- we could have a gc method that closes but files auto close anyway
+
local zerobased = { }
function files.open(filename,zb)
@@ -249,7 +253,7 @@ end
if bit32 then
- local rshift = bit32.rshift
+ local rshift = bit32.rshift
function files.writecardinal2(f,n)
local a = char(n % 256)
@@ -258,6 +262,35 @@ if bit32 then
f:write(b,a)
end
+ function files.writecardinal4(f,n)
+ local a = char(n % 256)
+ n = rshift(n,8)
+ local b = char(n % 256)
+ n = rshift(n,8)
+ local c = char(n % 256)
+ n = rshift(n,8)
+ local d = char(n % 256)
+ f:write(d,c,b,a)
+ end
+
+ function files.writecardinal2le(f,n)
+ local a = char(n % 256)
+ n = rshift(n,8)
+ local b = char(n % 256)
+ f:write(a,b)
+ end
+
+ function files.writecardinal4le(f,n)
+ local a = char(n % 256)
+ n = rshift(n,8)
+ local b = char(n % 256)
+ n = rshift(n,8)
+ local c = char(n % 256)
+ n = rshift(n,8)
+ local d = char(n % 256)
+ f:write(a,b,c,d)
+ end
+
else
local floor = math.floor
@@ -269,17 +302,35 @@ else
f:write(b,a)
end
-end
+ function files.writecardinal4(f,n)
+ local a = char(n % 256)
+ n = floor(n/256)
+ local b = char(n % 256)
+ n = floor(n/256)
+ local c = char(n % 256)
+ n = floor(n/256)
+ local d = char(n % 256)
+ f:write(d,c,b,a)
+ end
+
+ function files.writecardinal2le(f,n)
+ local a = char(n % 256)
+ n = floor(n/256)
+ local b = char(n % 256)
+ f:write(a,b)
+ end
+
+ function files.writecardinal4le(f,n)
+ local a = char(n % 256)
+ n = floor(n/256)
+ local b = char(n % 256)
+ n = floor(n/256)
+ local c = char(n % 256)
+ n = floor(n/256)
+ local d = char(n % 256)
+ f:write(a,b,c,d)
+ end
-function files.writecardinal4(f,n)
- local a = char(n % 256)
- n = rshift(n,8)
- local b = char(n % 256)
- n = rshift(n,8)
- local c = char(n % 256)
- n = rshift(n,8)
- local d = char(n % 256)
- f:write(d,c,b,a)
end
function files.writestring(f,s)
@@ -292,30 +343,42 @@ end
if fio and fio.readcardinal1 then
- files.readcardinal1 = fio.readcardinal1
- files.readcardinal2 = fio.readcardinal2
- files.readcardinal3 = fio.readcardinal3
- files.readcardinal4 = fio.readcardinal4
- files.readinteger1 = fio.readinteger1
- files.readinteger2 = fio.readinteger2
- files.readinteger3 = fio.readinteger3
- files.readinteger4 = fio.readinteger4
- files.readfixed2 = fio.readfixed2
- files.readfixed4 = fio.readfixed4
- files.read2dot14 = fio.read2dot14
- files.setposition = fio.setposition
- files.getposition = fio.getposition
-
- files.readbyte = files.readcardinal1
- files.readsignedbyte = files.readinteger1
- files.readcardinal = files.readcardinal1
- files.readinteger = files.readinteger1
-
- local skipposition = fio.skipposition
- files.skipposition = skipposition
-
- files.readbytes = fio.readbytes
- files.readbytetable = fio.readbytetable
+ files.readcardinal1 = fio.readcardinal1
+ files.readcardinal2 = fio.readcardinal2
+ files.readcardinal3 = fio.readcardinal3
+ files.readcardinal4 = fio.readcardinal4
+
+ files.readcardinal1le = fio.readcardinal1le or files.readcardinal1le
+ files.readcardinal2le = fio.readcardinal2le or files.readcardinal2le
+ files.readcardinal3le = fio.readcardinal3le or files.readcardinal3le
+ files.readcardinal4le = fio.readcardinal4le or files.readcardinal4le
+
+ files.readinteger1 = fio.readinteger1
+ files.readinteger2 = fio.readinteger2
+ files.readinteger3 = fio.readinteger3
+ files.readinteger4 = fio.readinteger4
+
+ files.readinteger1le = fio.readinteger1le or files.readinteger1le
+ files.readinteger2le = fio.readinteger2le or files.readinteger2le
+ files.readinteger3le = fio.readinteger3le or files.readinteger3le
+ files.readinteger4le = fio.readinteger4le or files.readinteger4le
+
+ files.readfixed2 = fio.readfixed2
+ files.readfixed4 = fio.readfixed4
+ files.read2dot14 = fio.read2dot14
+ files.setposition = fio.setposition
+ files.getposition = fio.getposition
+
+ files.readbyte = files.readcardinal1
+ files.readsignedbyte = files.readinteger1
+ files.readcardinal = files.readcardinal1
+ files.readinteger = files.readinteger1
+
+ local skipposition = fio.skipposition
+ files.skipposition = skipposition
+
+ files.readbytes = fio.readbytes
+ files.readbytetable = fio.readbytetable
function files.skipshort(f,n)
skipposition(f,2*(n or 1))
@@ -327,6 +390,30 @@ if fio and fio.readcardinal1 then
end
+if fio and fio.writecardinal1 then
+
+ files.writecardinal1 = fio.writecardinal1
+ files.writecardinal2 = fio.writecardinal2
+ files.writecardinal3 = fio.writecardinal3
+ files.writecardinal4 = fio.writecardinal4
+
+ files.writecardinal1le = fio.writecardinal1le
+ files.writecardinal2le = fio.writecardinal2le
+ files.writecardinal3le = fio.writecardinal3le
+ files.writecardinal4le = fio.writecardinal4le
+
+ files.writeinteger1 = fio.writeinteger1 or fio.writecardinal1
+ files.writeinteger2 = fio.writeinteger2 or fio.writecardinal2
+ files.writeinteger3 = fio.writeinteger3 or fio.writecardinal3
+ files.writeinteger4 = fio.writeinteger4 or fio.writecardinal4
+
+ files.writeinteger1le = files.writeinteger1le or fio.writecardinal1le
+ files.writeinteger2le = files.writeinteger2le or fio.writecardinal2le
+ files.writeinteger3le = files.writeinteger3le or fio.writecardinal3le
+ files.writeinteger4le = files.writeinteger4le or fio.writecardinal4le
+
+end
+
if fio and fio.readcardinaltable then
files.readcardinaltable = fio.readcardinaltable
diff --git a/tex/context/base/mkiv/util-fmt.lua b/tex/context/base/mkiv/util-fmt.lua
index 371a5dfce..fe80c6420 100644
--- a/tex/context/base/mkiv/util-fmt.lua
+++ b/tex/context/base/mkiv/util-fmt.lua
@@ -35,10 +35,17 @@ function formatters.formatcolumns(result,between)
for j=1,n do
local rj = r[j]
local tj = type(rj)
+-- if tj == "number" then
+-- numbers[j] = true
+-- end
+-- if tj ~= "string" then
+-- rj = tostring(rj)
+-- r[j] = rj
+-- end
if tj == "number" then
numbers[j] = true
- end
- if tj ~= "string" then
+ rj = tostring(rj)
+ elseif tj ~= "string" then
rj = tostring(rj)
r[j] = rj
end
diff --git a/tex/context/base/mkiv/util-prs.lua b/tex/context/base/mkiv/util-prs.lua
index 891f1096a..3154bf6c2 100644
--- a/tex/context/base/mkiv/util-prs.lua
+++ b/tex/context/base/mkiv/util-prs.lua
@@ -24,8 +24,8 @@ local sortedhash = table.sortedhash
local sortedkeys = table.sortedkeys
local tohash = table.tohash
-local hashes = { }
-utilities.parsers.hashes = hashes
+local hashes = { }
+parsers.hashes = hashes
-- we share some patterns
local digit = R("09")
@@ -308,7 +308,9 @@ end
function parsers.hash_to_string(h,separator,yes,no,strict,omit)
if h then
- local t, tn, s = { }, 0, sortedkeys(h)
+ local t = { }
+ local tn = 0
+ local s = sortedkeys(h)
omit = omit and tohash(omit)
for i=1,#s do
local key = s[i]
@@ -361,7 +363,7 @@ end
local pattern = Cf(Ct("") * Cg(C((1-S(", "))^1) * S(", ")^0 * Cc(true))^1,rawset)
-function utilities.parsers.settings_to_set(str)
+function parsers.settings_to_set(str)
return str and lpegmatch(pattern,str) or { }
end
@@ -374,7 +376,8 @@ end)
getmetatable(hashes.settings_to_set).__mode = "kv" -- could be an option (maybe sharing makes sense)
function parsers.simple_hash_to_string(h, separator)
- local t, tn = { }, 0
+ local t = { }
+ local tn = 0
for k, v in sortedhash(h) do
if v then
tn = tn + 1
@@ -390,13 +393,13 @@ local str = Cs(lpegpatterns.unquoted) + C((1-whitespace-equal)^1)
local setting = Cf( Carg(1) * (whitespace^0 * Cg(str * whitespace^0 * (equal * whitespace^0 * str + Cc(""))))^1,rawset)
local splitter = setting^1
-function utilities.parsers.options_to_hash(str,target)
+function parsers.options_to_hash(str,target)
return str and lpegmatch(splitter,str,1,target or { }) or { }
end
local splitter = lpeg.tsplitat(" ")
-function utilities.parsers.options_to_array(str)
+function parsers.options_to_array(str)
return str and lpegmatch(splitter,str) or { }
end
@@ -415,7 +418,8 @@ local function repeater(n,str)
if n == 1 then
return unpack(s)
else
- local t, tn = { }, 0
+ local t = { }
+ local tn = 0
for i=1,n do
for j=1,#s do
tn = tn + 1
@@ -557,7 +561,7 @@ end
-- and this is a slightly patched version of a version posted by Philipp Gesang
--- local mycsvsplitter = utilities.parsers.rfc4180splitter()
+-- local mycsvsplitter = parsers.rfc4180splitter()
-- local crap = [[
-- first,second,third,fourth
@@ -597,11 +601,11 @@ function parsers.rfc4180splitter(specification)
end
end
--- utilities.parsers.stepper("1,7-",9,function(i) print(">>>",i) end)
--- utilities.parsers.stepper("1-3,7,8,9")
--- utilities.parsers.stepper("1-3,6,7",function(i) print(">>>",i) end)
--- utilities.parsers.stepper(" 1 : 3, ,7 ")
--- utilities.parsers.stepper("1:4,9:13,24:*",30)
+-- parsers.stepper("1,7-",9,function(i) print(">>>",i) end)
+-- parsers.stepper("1-3,7,8,9")
+-- parsers.stepper("1-3,6,7",function(i) print(">>>",i) end)
+-- parsers.stepper(" 1 : 3, ,7 ")
+-- parsers.stepper("1:4,9:13,24:*",30)
local function ranger(first,last,n,action)
if not first then
@@ -654,7 +658,7 @@ function parsers.unittoxml(str)
return lpegmatch(pattern,str)
end
--- print(utilities.parsers.unittotex("10^-32 %"),utilities.parsers.unittoxml("10^32 %"))
+-- print(parsers.unittotex("10^-32 %"),utilities.parsers.unittoxml("10^32 %"))
local cache = { }
local spaces = lpegpatterns.space^0
@@ -670,7 +674,7 @@ end)
local commalistiterator = cache[","]
-function utilities.parsers.iterator(str,separator)
+function parsers.iterator(str,separator)
local n = #str
if n == 0 then
return dummy
@@ -689,7 +693,7 @@ function utilities.parsers.iterator(str,separator)
end
end
--- for s in utilities.parsers.iterator("a b c,b,c") do
+-- for s in parsers.iterator("a b c,b,c") do
-- print(s)
-- end
@@ -721,7 +725,7 @@ local name = C((1-S(", "))^1)
local parser = (Carg(1) * name / initialize) * (S(", ")^1 * (Carg(1) * name / fetch))^0
local merge = Cf(parser,process)
-function utilities.parsers.mergehashes(hash,list)
+function parsers.mergehashes(hash,list)
return lpegmatch(merge,list,1,hash)
end
@@ -731,9 +735,9 @@ end
-- cc = { epsilon = 3 },
-- }
--
--- inspect(utilities.parsers.mergehashes(t,"aa, bb, cc"))
+-- inspect(parsers.mergehashes(t,"aa, bb, cc"))
-function utilities.parsers.runtime(time)
+function parsers.runtime(time)
if not time then
time = os.runtime()
end
@@ -755,7 +759,7 @@ local token = lbrace * C((1-rbrace)^1) * rbrace + C(anything^1)
local pattern = spacing * (method * spacing * apply + Carg(1)) * spacing * token
-function utilities.parsers.splitmethod(str,default)
+function parsers.splitmethod(str,default)
if str then
return lpegmatch(pattern,str,1,default or false)
else
@@ -763,9 +767,38 @@ function utilities.parsers.splitmethod(str,default)
end
end
--- print(utilities.parsers.splitmethod(" foo -> {bar} "))
--- print(utilities.parsers.splitmethod("foo->{bar}"))
--- print(utilities.parsers.splitmethod("foo->bar"))
--- print(utilities.parsers.splitmethod("foo"))
--- print(utilities.parsers.splitmethod("{foo}"))
--- print(utilities.parsers.splitmethod())
+-- print(parsers.splitmethod(" foo -> {bar} "))
+-- print(parsers.splitmethod("foo->{bar}"))
+-- print(parsers.splitmethod("foo->bar"))
+-- print(parsers.splitmethod("foo"))
+-- print(parsers.splitmethod("{foo}"))
+-- print(parsers.splitmethod())
+
+local p_year = lpegpatterns.digit^4 / tonumber
+
+local pattern = Cf( Ct("") *
+ (
+ ( Cg(Cc("year") * p_year)
+ * S("-/") * Cg(Cc("month") * cardinal)
+ * S("-/") * Cg(Cc("day") * cardinal)
+ ) +
+ ( Cg(Cc("day") * cardinal)
+ * S("-/") * Cg(Cc("month") * cardinal)
+ * S("-/") * Cg(Cc("year") * p_year)
+ )
+ )
+ * P(" ") * Cg(Cc("hour") * cardinal)
+ * P(":") * Cg(Cc("min") * cardinal)
+ * (P(":") * Cg(Cc("sec") * cardinal))^-1
+, rawset)
+
+lpegpatterns.splittime = pattern
+
+function parsers.totime(str)
+ return lpegmatch(pattern,str)
+end
+
+-- print(os.time(parsers.totime("2019-03-05 12:12:12")))
+-- print(os.time(parsers.totime("2019/03/05 12:12:12")))
+-- print(os.time(parsers.totime("05-03-2019 12:12:12")))
+-- print(os.time(parsers.totime("05/03/2019 12:12:12")))
diff --git a/tex/context/base/mkiv/util-sac.lua b/tex/context/base/mkiv/util-sac.lua
index dc8ba72f1..976989a77 100644
--- a/tex/context/base/mkiv/util-sac.lua
+++ b/tex/context/base/mkiv/util-sac.lua
@@ -29,6 +29,12 @@ function streams.openstring(f,zerobased)
end
end
+function streams.getstring(f)
+ if f then
+ return f[1]
+ end
+end
+
function streams.close()
-- dummy
end
@@ -137,7 +143,7 @@ function streams.readcardinal2(f)
return 0x100 * a + b
end
-function streams.readcardinal2LE(f)
+function streams.readcardinal2le(f)
local i = f[2]
local j = i + 1
f[2] = j + 1
@@ -217,6 +223,14 @@ function streams.readcardinal4(f)
return 0x1000000 * a + 0x10000 * b + 0x100 * c + d
end
+function streams.readcardinal4le(f)
+ local i = f[2]
+ local j = i + 3
+ f[2] = j + 1
+ local d, c, b, a = byte(f[1],i,j)
+ return 0x1000000 * a + 0x10000 * b + 0x100 * c + d
+end
+
function streams.readinteger4(f)
local i = f[2]
local j = i + 3
diff --git a/tex/context/base/mkiv/util-soc-imp-copas.lua b/tex/context/base/mkiv/util-soc-imp-copas.lua
index 3e66e5888..1268613d1 100644
--- a/tex/context/base/mkiv/util-soc-imp-copas.lua
+++ b/tex/context/base/mkiv/util-soc-imp-copas.lua
@@ -50,6 +50,8 @@ local copas = {
report = report,
+ trace = false,
+
}
local function statushandler(status, ...)
@@ -60,7 +62,9 @@ local function statushandler(status, ...)
if type(err) == "table" then
err = err[1]
end
- report("error: %s",tostring(err))
+ if copas.trace then
+ report("error: %s",tostring(err))
+ end
return nil, err
end
@@ -76,7 +80,9 @@ function socket.newtry(finalizer)
if not status then
local detail = select(2,...)
pcall(finalizer,detail)
- report("error: %s",tostring(detail))
+ if copas.trace then
+ report("error: %s",tostring(detail))
+ end
return
end
return ...
diff --git a/tex/context/base/mkiv/util-soc-imp-mime.lua b/tex/context/base/mkiv/util-soc-imp-mime.lua
index 4b5d2baff..7a5cef27b 100644
--- a/tex/context/base/mkiv/util-soc-imp-mime.lua
+++ b/tex/context/base/mkiv/util-soc-imp-mime.lua
@@ -3,8 +3,8 @@
local type, tostring = type, tostring
-local mime = require("mime.core")
-local ltn12 = ltn12 or require("ltn12")
+local mime = mime or package.loaded.mime or require("mime.core")
+local ltn12 = ltn12 or package.loaded.ltn12 or require("ltn12")
local filtercycle = ltn12.filter.cycle
diff --git a/tex/context/base/mkiv/util-soc-imp-socket.lua b/tex/context/base/mkiv/util-soc-imp-socket.lua
index 3da155749..d1486f8f8 100644
--- a/tex/context/base/mkiv/util-soc-imp-socket.lua
+++ b/tex/context/base/mkiv/util-soc-imp-socket.lua
@@ -5,7 +5,7 @@ local type, tostring, setmetatable = type, tostring, setmetatable
local min = math.min
local format = string.format
-local socket = require("socket.core")
+local socket = socket or package.loaded.socket or require("socket.core")
local connect = socket.connect
local tcp4 = socket.tcp4
diff --git a/tex/context/base/mkiv/util-str.lua b/tex/context/base/mkiv/util-str.lua
index 713c294eb..5470c2fd6 100644
--- a/tex/context/base/mkiv/util-str.lua
+++ b/tex/context/base/mkiv/util-str.lua
@@ -14,7 +14,6 @@ local format, gsub, rep, sub, find = string.format, string.gsub, string.rep, str
local load, dump = load, string.dump
local tonumber, type, tostring, next, setmetatable = tonumber, type, tostring, next, setmetatable
local unpack, concat = table.unpack, table.concat
-local unpack, concat = table.unpack, table.concat
local P, V, C, S, R, Ct, Cs, Cp, Carg, Cc = lpeg.P, lpeg.V, lpeg.C, lpeg.S, lpeg.R, lpeg.Ct, lpeg.Cs, lpeg.Cp, lpeg.Carg, lpeg.Cc
local patterns, lpegmatch = lpeg.patterns, lpeg.match
local utfchar, utfbyte, utflen = utf.char, utf.byte, utf.len
@@ -610,8 +609,8 @@ local environment = {
formattednumber = number.formatted,
sparseexponent = number.sparseexponent,
formattedfloat = number.formattedfloat,
- stripzero = lpeg.patterns.stripzero,
- stripzeros = lpeg.patterns.stripzeros,
+ stripzero = patterns.stripzero,
+ stripzeros = patterns.stripzeros,
FORMAT = string.f9,
}
@@ -745,7 +744,7 @@ end
local format_k = function(b,a) -- slow
n = n + 1
- return format("formattedfloat(a%s,%i,%i)",n,b or 0, a or 0)
+ return format("formattedfloat(a%s,%s,%s)",n,b or 0,a or 0)
end
local format_g = function(f)
@@ -1329,9 +1328,9 @@ patterns.luaquoted = Cs(Cc('"') * ((1-S('"\n'))^1 + P('"')/'\\"' + P('\n')/'\\n"
-- escaping by lpeg is faster for strings without quotes, slower on a string with quotes, but
-- faster again when other q-escapables are found (the ones we don't need to escape)
-add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],{ xmlescape = lpeg.patterns.xmlescape })
-add(formatters,"tex",[[lpegmatch(texescape,%s)]],{ texescape = lpeg.patterns.texescape })
-add(formatters,"lua",[[lpegmatch(luaescape,%s)]],{ luaescape = lpeg.patterns.luaescape })
+add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],{ xmlescape = patterns.xmlescape })
+add(formatters,"tex",[[lpegmatch(texescape,%s)]],{ texescape = patterns.texescape })
+add(formatters,"lua",[[lpegmatch(luaescape,%s)]],{ luaescape = patterns.luaescape })
-- -- yes or no:
--
@@ -1409,3 +1408,31 @@ local f_16_16 = formatters["%0.5N"]
function number.to16dot16(n)
return f_16_16(n/65536.0)
end
+
+--
+
+if not string.explode then
+
+ local tsplitat = lpeg.tsplitat
+
+ local p_utf = patterns.utf8character
+ local p_check = C(p_utf) * (P("+") * Cc(true))^0
+ local p_split = Ct(C(p_utf)^0)
+ local p_space = Ct((C(1-P(" ")^1) + P(" ")^1)^0)
+
+ function string.explode(str,symbol)
+ if symbol == "" then
+ return lpegmatch(p_split,str)
+ elseif symbol then
+ local a, b = lpegmatch(p_check,symbol)
+ if b then
+ return lpegmatch(tsplitat(P(a)^1),str)
+ else
+ return lpegmatch(tsplitat(a),str)
+ end
+ else
+ return lpegmatch(p_space,str)
+ end
+ end
+
+end
diff --git a/tex/context/base/mkiv/util-tab.lua b/tex/context/base/mkiv/util-tab.lua
index ed4cef996..2f425cca3 100644
--- a/tex/context/base/mkiv/util-tab.lua
+++ b/tex/context/base/mkiv/util-tab.lua
@@ -22,7 +22,8 @@ local utftoeight = utf.toeight
local splitter = lpeg.tsplitat(".")
function utilities.tables.definetable(target,nofirst,nolast) -- defines undefined tables
- local composed, t = nil, { }
+ local composed = nil
+ local t = { }
local snippets = lpegmatch(splitter,target)
for i=1,#snippets - (nolast and 1 or 0) do
local name = snippets[i]
@@ -310,7 +311,8 @@ function tables.encapsulate(core,capsule,protect)
end
end
--- best keep [%q] keys (as we have some in older applications i.e. saving user data
+-- best keep [%q] keys (as we have some in older applications i.e. saving user data (otherwise
+-- we also need to check for reserved words)
local f_hashed_string = formatters["[%q]=%q,"]
local f_hashed_number = formatters["[%q]=%s,"]
@@ -334,7 +336,6 @@ function table.fastserialize(t,prefix)
local r = { type(prefix) == "string" and prefix or "return" }
local m = 1
-
local function fastserialize(t,outer) -- no mixes
local n = #t
m = m + 1
@@ -654,19 +655,20 @@ local function serialize(root,name,specification)
-- we could check for k (index) being number (cardinal)
if root and next(root) ~= nil then
local first = nil
- local last = 0
- last = #root
- for k=1,last do
- if rawget(root,k) == nil then
- -- if root[k] == nil then
- last = k - 1
- break
- end
- end
+ local last = #root
if last > 0 then
- first = 1
+ for k=1,last do
+ if rawget(root,k) == nil then
+ -- if root[k] == nil then
+ last = k - 1
+ break
+ end
+ end
+ if last > 0 then
+ first = 1
+ end
end
- local sk = sortedkeys(root) -- inline fast version?\
+ local sk = sortedkeys(root)
for i=1,#sk do
local k = sk[i]
local v = root[k]
diff --git a/tex/context/base/mkiv/util-zip.lua b/tex/context/base/mkiv/util-zip.lua
new file mode 100644
index 000000000..7d252a74f
--- /dev/null
+++ b/tex/context/base/mkiv/util-zip.lua
@@ -0,0 +1,549 @@
+if not modules then modules = { } end modules ['util-zip'] = {
+ version = 1.001,
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This module is mostly meant for relative simple zip and unzip tasks. We can read
+-- and write zip files but with limitations. Performance is quite good and it makes
+-- us independent of zip tools, which (for some reason) are not always installed.
+--
+-- This is an lmtx module and at some point will be lmtx only but for a while we
+-- keep some hybrid functionality.
+
+local type, tostring, tonumber = type, tostring, tonumber
+local sort = table.sort
+
+local find, format, sub, gsub = string.find, string.format, string.sub, string.gsub
+local osdate, ostime = os.date, os.time
+local ioopen = io.open
+local loaddata, savedata = io.loaddata, io.savedata
+local filejoin, isdir, dirname, mkdirs = file.join, lfs.isdir, file.dirname, dir.mkdirs
+
+local files = utilities.files
+local openfile = files.open
+local closefile = files.close
+local readstring = files.readstring
+local readcardinal2 = files.readcardinal2le
+local readcardinal4 = files.readcardinal4le
+local setposition = files.setposition
+local getposition = files.getposition
+
+local band = bit32.band
+local rshift = bit32.rshift
+local lshift = bit32.lshift
+
+local decompress, calculatecrc
+
+if flate then
+
+ decompress = flate.flate_decompress
+ calculatecrc = flate.update_crc32
+
+else
+
+ local zlibdecompress = zlib.decompress
+ local zlibchecksum = zlib.crc32
+
+ decompress = function(source,targetsize)
+ local target = zlibdecompress(source,-15)
+ if target then
+ return target
+ else
+ return false, 1
+ end
+ end
+
+ calculatecrc = function(buffer,initial)
+ return zlibchecksum(initial or 0,buffer)
+ end
+
+end
+
+local zipfiles = { }
+utilities.zipfiles = zipfiles
+
+local openzipfile, closezipfile, unzipfile, foundzipfile, getziphash, getziplist do
+
+ function openzipfile(name)
+ return {
+ name = name,
+ handle = openfile(name,0),
+ }
+ end
+
+ local function collect(z)
+ if not z.list then
+ local list = { }
+ local hash = { }
+ local position = 0
+ local index = 0
+ local handle = z.handle
+ while true do
+ setposition(handle,position)
+ local signature = readstring(handle,4)
+ if signature == "PK\3\4" then
+ -- [local file header 1]
+ -- [encryption header 1]
+ -- [file data 1]
+ -- [data descriptor 1]
+ local version = readcardinal2(handle)
+ local flag = readcardinal2(handle)
+ local method = readcardinal2(handle)
+ local filetime = readcardinal2(handle)
+ local filedate = readcardinal2(handle)
+ local crc32 = readcardinal4(handle)
+ local compressed = readcardinal4(handle)
+ local uncompressed = readcardinal4(handle)
+ local namelength = readcardinal2(handle)
+ local extralength = readcardinal2(handle)
+ local filename = readstring(handle,namelength)
+ local descriptor = band(flag,8) ~= 0
+ local encrypted = band(flag,1) ~= 0
+ local acceptable = method == 0 or method == 8
+ -- 30 bytes of header including the signature
+ local skipped = 0
+ local size = 0
+ if encrypted then
+ size = readcardinal2(handle)
+ skipbytes(size)
+ skipped = skipped + size + 2
+ skipbytes(8)
+ skipped = skipped + 8
+ size = readcardinal2(handle)
+ skipbytes(size)
+ skipped = skipped + size + 2
+ size = readcardinal4(handle)
+ skipbytes(size)
+ skipped = skipped + size + 4
+ size = readcardinal2(handle)
+ skipbytes(size)
+ skipped = skipped + size + 2
+ end
+ position = position + 30 + namelength + extralength + skipped
+ if descriptor then
+ setposition(handle,position + compressed)
+ crc32 = readcardinal4(handle)
+ compressed = readcardinal4(handle)
+ uncompressed = readcardinal4(handle)
+ end
+ if acceptable then
+ index = index + 1
+ local data = {
+ filename = filename,
+ index = index,
+ position = position,
+ method = method,
+ compressed = compressed,
+ uncompressed = uncompressed,
+ crc32 = crc32,
+ encrypted = encrypted,
+ }
+ hash[filename] = data
+ list[index] = data
+ else
+ -- maybe a warning when encrypted
+ end
+ position = position + compressed
+ else
+ break
+ end
+ z.list = list
+ z.hash = hash
+ end
+ end
+ end
+
+ function getziplist(z)
+ local list = z.list
+ if not list then
+ collect(z)
+ end
+ return z.list
+ end
+
+ function getziphash(z)
+ local hash = z.hash
+ if not hash then
+ collect(z)
+ end
+ return z.hash
+ end
+
+ function foundzipfile(z,name)
+ return getziphash(z)[name]
+ end
+
+ function closezipfile(z)
+ local f = z.handle
+ if f then
+ closefile(f)
+ z.handle = nil
+ end
+ end
+
+ function unzipfile(z,filename,check)
+ local hash = z.hash
+ if not hash then
+ hash = zipfiles.hash(z)
+ end
+ local data = hash[filename] -- normalize
+ if not data then
+ -- lower and cleanup
+ -- only name
+ end
+ if data then
+ local handle = z.handle
+ local position = data.position
+ local compressed = data.compressed
+ if compressed > 0 then
+ setposition(handle,position)
+ local result = readstring(handle,compressed)
+ if data.method == 8 then
+ result = decompress(result,data.uncompressed)
+ end
+ if check and data.crc32 ~= calculatecrc(result) then
+ print("checksum mismatch")
+ return ""
+ end
+ return result
+ else
+ return ""
+ end
+ end
+ end
+
+ zipfiles.open = openzipfile
+ zipfiles.close = closezipfile
+ zipfiles.unzip = unzipfile
+ zipfiles.hash = getziphash
+ zipfiles.list = getziplist
+ zipfiles.found = foundzipfile
+
+end
+
+if flate then do
+
+ local writecardinal1 = files.writebyte
+ local writecardinal2 = files.writecardinal2le
+ local writecardinal4 = files.writecardinal4le
+
+ local logwriter = logs.writer
+
+ local globpattern = dir.globpattern
+ local compress = flate.flate_compress
+ local checksum = flate.update_crc32
+
+ -- local function fromdostime(dostime,dosdate)
+ -- return ostime {
+ -- year = (dosdate >> 9) + 1980, -- 25 .. 31
+ -- month = (dosdate >> 5) & 0x0F, -- 21 .. 24
+ -- day = (dosdate ) & 0x1F, -- 16 .. 20
+ -- hour = (dostime >> 11) , -- 11 .. 15
+ -- min = (dostime >> 5) & 0x3F, -- 5 .. 10
+ -- sec = (dostime ) & 0x1F, -- 0 .. 4
+ -- }
+ -- end
+ --
+ -- local function todostime(time)
+ -- local t = osdate("*t",time)
+ -- return
+ -- ((t.year - 1980) << 9) + (t.month << 5) + t.day,
+ -- (t.hour << 11) + (t.min << 5) + (t.sec >> 1)
+ -- end
+
+ local function fromdostime(dostime,dosdate)
+ return ostime {
+ year = rshift(dosdate, 9) + 1980, -- 25 .. 31
+ month = band(rshift(dosdate, 5), 0x0F), -- 21 .. 24
+ day = band( (dosdate ), 0x1F), -- 16 .. 20
+ hour = band(rshift(dostime,11) ), -- 11 .. 15
+ min = band(rshift(dostime, 5), 0x3F), -- 5 .. 10
+ sec = band( (dostime ), 0x1F), -- 0 .. 4
+ }
+ end
+
+ local function todostime(time)
+ local t = osdate("*t",time)
+ return
+ lshift(t.year - 1980, 9) + lshift(t.month,5) + t.day,
+ lshift(t.hour ,11) + lshift(t.min ,5) + rshift(t.sec,1)
+ end
+
+ local function openzip(filename,level,comment,verbose)
+ local f = ioopen(filename,"wb")
+ if f then
+ return {
+ filename = filename,
+ handle = f,
+ list = { },
+ level = tonumber(level) or 3,
+ comment = tostring(comment),
+ verbose = verbose,
+ uncompressed = 0,
+ compressed = 0,
+ }
+ end
+ end
+
+ local function writezip(z,name,data,level,time)
+ local f = z.handle
+ local list = z.list
+ local level = tonumber(level) or z.level or 3
+ local method = 8
+ local zipped = compress(data,level)
+ local checksum = checksum(data)
+ local verbose = z.verbose
+ --
+ if not zipped then
+ method = 0
+ zipped = data
+ end
+ --
+ local start = f:seek()
+ local compressed = #zipped
+ local uncompressed = #data
+ --
+ z.compressed = z.compressed + compressed
+ z.uncompressed = z.uncompressed + uncompressed
+ --
+ if verbose then
+ local pct = 100 * compressed/uncompressed
+ if pct >= 100 then
+ logwriter(format("%10i %s",uncompressed,name))
+ else
+ logwriter(format("%10i %02.1f %s",uncompressed,pct,name))
+ end
+ end
+ --
+ f:write("\x50\x4b\x03\x04") -- PK.. 0x04034b50
+ --
+ writecardinal2(f,0) -- minimum version
+ writecardinal2(f,0) -- flag
+ writecardinal2(f,method) -- method
+ writecardinal2(f,0) -- time
+ writecardinal2(f,0) -- date
+ writecardinal4(f,checksum) -- crc32
+ writecardinal4(f,compressed) -- compressed
+ writecardinal4(f,uncompressed) -- uncompressed
+ writecardinal2(f,#name) -- namelength
+ writecardinal2(f,0) -- extralength
+ --
+ f:write(name) -- name
+ f:write(zipped)
+ --
+ list[#list+1] = { #zipped, #data, name, checksum, start, time or 0 }
+ end
+
+ local function closezip(z)
+ local f = z.handle
+ local list = z.list
+ local comment = z.comment
+ local verbose = z.verbose
+ local count = #list
+ local start = f:seek()
+ --
+ for i=1,count do
+ local l = list[i]
+ local compressed = l[1]
+ local uncompressed = l[2]
+ local name = l[3]
+ local checksum = l[4]
+ local start = l[5]
+ local time = l[6]
+ local date, time = todostime(time)
+ f:write('\x50\x4b\x01\x02')
+ writecardinal2(f,0) -- version made by
+ writecardinal2(f,0) -- version needed to extract
+ writecardinal2(f,0) -- flags
+ writecardinal2(f,8) -- method
+ writecardinal2(f,time) -- time
+ writecardinal2(f,date) -- date
+ writecardinal4(f,checksum) -- crc32
+ writecardinal4(f,compressed) -- compressed
+ writecardinal4(f,uncompressed) -- uncompressed
+ writecardinal2(f,#name) -- namelength
+ writecardinal2(f,0) -- extralength
+ writecardinal2(f,0) -- commentlength
+ writecardinal2(f,0) -- nofdisks -- ?
+ writecardinal2(f,0) -- internal attr (type)
+ writecardinal4(f,0) -- external attr (mode)
+ writecardinal4(f,start) -- local offset
+ f:write(name) -- name
+ end
+ --
+ local stop = f:seek()
+ local size = stop - start
+ --
+ f:write('\x50\x4b\x05\x06')
+ writecardinal2(f,0) -- disk
+ writecardinal2(f,0) -- disks
+ writecardinal2(f,count) -- entries
+ writecardinal2(f,count) -- entries
+ writecardinal4(f,size) -- dir size
+ writecardinal4(f,start) -- dir offset
+ if type(comment) == "string" and comment ~= "" then
+ writecardinal2(f,#comment) -- comment length
+ f:write(comment) -- comemnt
+ else
+ writecardinal2(f,0)
+ end
+ --
+ if verbose then
+ local compressed = z.compressed
+ local uncompressed = z.uncompressed
+ local filename = z.filename
+ --
+ local pct = 100 * compressed/uncompressed
+ logwriter("")
+ if pct >= 100 then
+ logwriter(format("%10i %s",uncompressed,filename))
+ else
+ logwriter(format("%10i %02.1f %s",uncompressed,pct,filename))
+ end
+ end
+ --
+ f:close()
+ end
+
+ local function zipdir(zipname,path,level,verbose)
+ if type(zipname) == "table" then
+ verbose = zipname.verbose
+ level = zipname.level
+ path = zipname.path
+ zipname = zipname.zipname
+ end
+ if not zipname or zipname == "" then
+ return
+ end
+ if not path or path == "" then
+ path = "."
+ end
+ if not isdir(path) then
+ return
+ end
+ path = gsub(path,"\\+","/")
+ path = gsub(path,"/+","/")
+ local list = { }
+ local count = 0
+ globpattern(path,"",true,function(name,size,time)
+ count = count + 1
+ list[count] = { name, time }
+ end)
+ sort(list,function(a,b)
+ return a[1] < b[1]
+ end)
+ local zipf = openzip(zipname,level,comment,verbose)
+ if zipf then
+ local p = #path + 2
+ for i=1,count do
+ local li = list[i]
+ local name = li[1]
+ local time = li[2]
+ local data = loaddata(name)
+ local name = sub(name,p,#name)
+ writezip(zipf,name,data,level,time,verbose)
+ end
+ closezip(zipf)
+ end
+ end
+
+ local function unzipdir(zipname,path,verbose)
+ if type(zipname) == "table" then
+ verbose = zipname.verbose
+ path = zipname.path
+ zipname = zipname.zipname
+ end
+ if not zipname or zipname == "" then
+ return
+ end
+ if not path or path == "" then
+ path = "."
+ end
+ local z = openzipfile(zipname)
+ if z then
+ local list = getziplist(z)
+ if list then
+ local total = 0
+ local count = #list
+ local step = number.idiv(count,10)
+ local done = 0
+ for i=1,count do
+ local l = list[i]
+ local n = l.filename
+ local d = unzipfile(z,n) -- true for check
+ local p = filejoin(path,n)
+ if mkdirs(dirname(p)) then
+ if verbose == "steps" then
+ total = total + #d
+ done = done + 1
+ if done >= step then
+ done = 0
+ logwriter(format("%4i files of %4i done, %10i bytes",i,count,total))
+ end
+ elseif verbose then
+ logwriter(n)
+ end
+ savedata(p,d)
+ end
+ end
+ if verbose == "steps" then
+ logwriter(format("%4i files of %4i done, %10i bytes",count,count,total))
+ end
+ closezipfile(z)
+ return true
+ else
+ closezipfile(z)
+ end
+ end
+ end
+
+ zipfiles.zipdir = zipdir
+ zipfiles.unzipdir = unzipdir
+
+end end
+
+if flate then
+
+ local streams = utilities.streams
+ local openfile = streams.open
+ local closestream = streams.close
+ local setposition = streams.setposition
+ local getsize = streams.size
+ local readcardinal4 = streams.readcardinal4le
+ local getstring = streams.getstring
+ local decompress = flate.gz_decompress
+
+ -- id1=1 id2=1 method=1 flags=1 mtime=4(le) extra=1 os=1
+ -- flags:8 comment=...<nul> flags:4 name=...<nul> flags:2 extra=...<nul> flags:1 crc=2
+ -- data:?
+ -- crc=4 size=4
+
+ function zipfiles.gunzipfile(filename)
+ local strm = openfile(filename)
+ if strm then
+ setposition(strm,getsize(strm) - 4 + 1)
+ local size = readcardinal4(strm)
+ local data = decompress(getstring(strm),size)
+ closestream(strm)
+ return data
+ end
+ end
+
+elseif gzip then
+
+ local openfile = gzip.open
+
+ function zipfiles.gunzipfile(filename)
+ local g = openfile(filename,"rb")
+ if g then
+ local d = g:read("*a")
+ d:close()
+ return d
+ end
+ end
+
+end
+
+return zipfiles
diff --git a/tex/context/fonts/mkiv/type-imp-plex.mkiv b/tex/context/fonts/mkiv/type-imp-plex.mkiv
index 44334bcbd..02de45022 100644
--- a/tex/context/fonts/mkiv/type-imp-plex.mkiv
+++ b/tex/context/fonts/mkiv/type-imp-plex.mkiv
@@ -45,80 +45,80 @@
\starttypescript [\s!sans,\s!serif,\s!mono] [plex-thin] [\s!name]
\setups[\s!font:\s!fallback:\typescriptone]
- \definefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:plex\typescriptone}-thin] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Italic] [\s!file:\typescriptprefix{n:plex\typescriptone}-thinitalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone}-light] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!BoldItalic] [\s!file:\typescriptprefix{n:plex\typescriptone}-light] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:plex\typescriptone}-thin] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Italic] [\s!file:\typescriptprefix{n:plex\typescriptone}-thinitalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone}-light] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!BoldItalic] [\s!file:\typescriptprefix{n:plex\typescriptone}-light] [\s!features=\typescriptprefix{f:plex\typescriptone}]
\stoptypescript
% extralight
\starttypescript [\s!sans,\s!serif,\s!mono] [plex-extralight] [\s!name]
\setups[\s!font:\s!fallback:\typescriptone]
- \definefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:plex\typescriptone}-extralight] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Italic] [\s!file:\typescriptprefix{n:plex\typescriptone}-extralightitalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone}-regular] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!BoldItalic] [\s!file:\typescriptprefix{n:plex\typescriptone}-italic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:plex\typescriptone}-extralight] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Italic] [\s!file:\typescriptprefix{n:plex\typescriptone}-extralightitalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone}-regular] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!BoldItalic] [\s!file:\typescriptprefix{n:plex\typescriptone}-italic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
\stoptypescript
% light
\starttypescript [\s!sans,\s!serif,\s!mono] [plex-light] [\s!name]
\setups[\s!font:\s!fallback:\typescriptone]
- \definefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:plex\typescriptone}-light] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Italic] [\s!file:\typescriptprefix{n:plex\typescriptone}-lightitalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone}-text] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!BoldItalic] [\s!file:\typescriptprefix{n:plex\typescriptone}-textitalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:plex\typescriptone}-light] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Italic] [\s!file:\typescriptprefix{n:plex\typescriptone}-lightitalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone}-text] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!BoldItalic] [\s!file:\typescriptprefix{n:plex\typescriptone}-textitalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
\stoptypescript
% regular
\starttypescript [\s!sans,\s!serif,\s!mono] [plex] [\s!name]
\setups[\s!font:\s!fallback:\typescriptone]
- \definefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:plex\typescriptone}-regular] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Italic] [\s!file:\typescriptprefix{n:plex\typescriptone}-italic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone}-medium] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!BoldItalic] [\s!file:\typescriptprefix{n:plex\typescriptone}-mediumitalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:plex\typescriptone}-regular] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Italic] [\s!file:\typescriptprefix{n:plex\typescriptone}-italic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone}-medium] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!BoldItalic] [\s!file:\typescriptprefix{n:plex\typescriptone}-mediumitalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
\stoptypescript
% text
\starttypescript [\s!sans,\s!serif,\s!mono] [plex-text] [\s!name]
\setups[\s!font:\s!fallback:\typescriptone]
- \definefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:plex\typescriptone}-text] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Italic] [\s!file:\typescriptprefix{n:plex\typescriptone}-textitalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone}-semibold] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!BoldItalic] [\s!file:\typescriptprefix{n:plex\typescriptone}-semibolditalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:plex\typescriptone}-text] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Italic] [\s!file:\typescriptprefix{n:plex\typescriptone}-textitalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone}-semibold] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!BoldItalic] [\s!file:\typescriptprefix{n:plex\typescriptone}-semibolditalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
\stoptypescript
% medium
\starttypescript [\s!sans,\s!serif,\s!mono] [plex-medium] [\s!name]
\setups[\s!font:\s!fallback:\typescriptone]
- \definefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:plex\typescriptone}-medium] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Italic] [\s!file:\typescriptprefix{n:plex\typescriptone}-mediumitalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone}-bold] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!BoldItalic] [\s!file:\typescriptprefix{n:plex\typescriptone}-bolditalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:plex\typescriptone}-medium] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Italic] [\s!file:\typescriptprefix{n:plex\typescriptone}-mediumitalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone}-bold] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!BoldItalic] [\s!file:\typescriptprefix{n:plex\typescriptone}-bolditalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
\stoptypescript
% semibold
\starttypescript [\s!sans,\s!serif,\s!mono] [plex-semibold] [\s!name]
\setups[\s!font:\s!fallback:\typescriptone]
- \definefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:plex\typescriptone}-semibold] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Italic] [\s!file:\typescriptprefix{n:plex\typescriptone}-semibolditalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone}-extra] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!BoldItalic] [\s!file:\typescriptprefix{n:plex\typescriptone}-extraitalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:plex\typescriptone}-semibold] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Italic] [\s!file:\typescriptprefix{n:plex\typescriptone}-semibolditalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone}-extra] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!BoldItalic] [\s!file:\typescriptprefix{n:plex\typescriptone}-extraitalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
\stoptypescript
% bold
\starttypescript [\s!sans,\s!serif,\s!mono] [plex-bold] [\s!name]
\setups[\s!font:\s!fallback:\typescriptone]
- \definefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:plex\typescriptone}-bold] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Italic] [\s!file:\typescriptprefix{n:plex\typescriptone}-bolditalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone}-bold] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!BoldItalic] [\s!file:\typescriptprefix{n:plex\typescriptone}-bolditalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:plex\typescriptone}-bold] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Italic] [\s!file:\typescriptprefix{n:plex\typescriptone}-bolditalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone}-bold] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!BoldItalic] [\s!file:\typescriptprefix{n:plex\typescriptone}-bolditalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
\stoptypescript
% done
@@ -144,92 +144,92 @@
\starttypescript [\s!sans,\s!serif,\s!mono] [ibmplex-thin] [\s!name]
\setups[\s!font:\s!fallback:\typescriptone]
- \definefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:plex\typescriptone}-thin] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Italic] [\s!file:\typescriptprefix{n:plex\typescriptone}-thinitalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone}-text] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!BoldItalic] [\s!file:\typescriptprefix{n:plex\typescriptone}-textitalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}Widened] [\s!file:\typescriptprefix{n:plex\typescriptone}-thin] [\s!features=\typescriptprefix{f:scplex\typescriptone}]
- \definefontfallback[Fake\typescriptprefix{\typescriptone}Caps] [\typescriptprefix{\typescriptone}Widened] [0x0000-0xFFFF] [\s!rscale=0.85,method=uppercase]
- \definefontsynonym [\typescriptprefix{\typescriptone}Caps] [\s!file:\typescriptprefix{n:plex\typescriptone}-thin] [\s!fallbacks=Fake\typescriptprefix{\typescriptone}Caps]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:plex\typescriptone}-thin] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Italic] [\s!file:\typescriptprefix{n:plex\typescriptone}-thinitalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone}-text] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!BoldItalic] [\s!file:\typescriptprefix{n:plex\typescriptone}-textitalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}Widened] [\s!file:\typescriptprefix{n:plex\typescriptone}-thin] [\s!features=\typescriptprefix{f:scplex\typescriptone}]
+ \edefinefontfallback[Fake\typescriptprefix{\typescriptone}Caps] [\typescriptprefix{\typescriptone}Widened] [0x0000-0xFFFF] [\s!rscale=0.85,method=uppercase]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}Caps] [\s!file:\typescriptprefix{n:plex\typescriptone}-thin] [\s!fallbacks=Fake\typescriptprefix{\typescriptone}Caps]
\stoptypescript
\starttypescript [\s!sans,\s!serif,\s!mono] [ibmplex-extralight] [\s!name]
\setups[\s!font:\s!fallback:\typescriptone]
- \definefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:plex\typescriptone}-extralight] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Italic] [\s!file:\typescriptprefix{n:plex\typescriptone}-extralightitalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone}-medium] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!BoldItalic] [\s!file:\typescriptprefix{n:plex\typescriptone}-mediumitalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}Widened] [\s!file:\typescriptprefix{n:plex\typescriptone}-extralight] [\s!features=\typescriptprefix{f:scplex\typescriptone}]
- \definefontfallback[Fake\typescriptprefix{\typescriptone}Caps] [\typescriptprefix{\typescriptone}Widened] [0x0000-0xFFFF] [\s!rscale=0.85,method=uppercase]
- \definefontsynonym [\typescriptprefix{\typescriptone}Caps] [\s!file:\typescriptprefix{n:plex\typescriptone}-extralight] [\s!fallbacks=Fake\typescriptprefix{\typescriptone}Caps]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:plex\typescriptone}-extralight] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Italic] [\s!file:\typescriptprefix{n:plex\typescriptone}-extralightitalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone}-medium] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!BoldItalic] [\s!file:\typescriptprefix{n:plex\typescriptone}-mediumitalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}Widened] [\s!file:\typescriptprefix{n:plex\typescriptone}-extralight] [\s!features=\typescriptprefix{f:scplex\typescriptone}]
+ \edefinefontfallback[Fake\typescriptprefix{\typescriptone}Caps] [\typescriptprefix{\typescriptone}Widened] [0x0000-0xFFFF] [\s!rscale=0.85,method=uppercase]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}Caps] [\s!file:\typescriptprefix{n:plex\typescriptone}-extralight] [\s!fallbacks=Fake\typescriptprefix{\typescriptone}Caps]
\stoptypescript
\starttypescript [\s!sans,\s!serif,\s!mono] [ibmplex-light] [\s!name]
\setups[\s!font:\s!fallback:\typescriptone]
- \definefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:plex\typescriptone}-light] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Italic] [\s!file:\typescriptprefix{n:plex\typescriptone}-lightitalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone}-semibold] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!BoldItalic] [\s!file:\typescriptprefix{n:plex\typescriptone}-semibolditalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}Widened] [\s!file:\typescriptprefix{n:plex\typescriptone}-light] [\s!features=\typescriptprefix{f:scplex\typescriptone}]
- \definefontfallback[Fake\typescriptprefix{\typescriptone}Caps] [\typescriptprefix{\typescriptone}Widened] [0x0000-0xFFFF] [\s!rscale=0.85,method=uppercase]
- \definefontsynonym [\typescriptprefix{\typescriptone}Caps] [\s!file:\typescriptprefix{n:plex\typescriptone}-light] [\s!fallbacks=Fake\typescriptprefix{\typescriptone}Caps]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:plex\typescriptone}-light] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Italic] [\s!file:\typescriptprefix{n:plex\typescriptone}-lightitalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone}-semibold] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!BoldItalic] [\s!file:\typescriptprefix{n:plex\typescriptone}-semibolditalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}Widened] [\s!file:\typescriptprefix{n:plex\typescriptone}-light] [\s!features=\typescriptprefix{f:scplex\typescriptone}]
+ \edefinefontfallback[Fake\typescriptprefix{\typescriptone}Caps] [\typescriptprefix{\typescriptone}Widened] [0x0000-0xFFFF] [\s!rscale=0.85,method=uppercase]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}Caps] [\s!file:\typescriptprefix{n:plex\typescriptone}-light] [\s!fallbacks=Fake\typescriptprefix{\typescriptone}Caps]
\stoptypescript
\starttypescript [\s!sans,\s!serif,\s!mono] [ibmplex] [\s!name]
\setups[\s!font:\s!fallback:\typescriptone]
- \definefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:plex\typescriptone}-regular] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Italic] [\s!file:\typescriptprefix{n:plex\typescriptone}-italic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone}-bold] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!BoldItalic] [\s!file:\typescriptprefix{n:plex\typescriptone}-bolditalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}Widened] [\s!file:\typescriptprefix{n:plex\typescriptone}-regular] [\s!features=\typescriptprefix{f:scplex\typescriptone}]
- \definefontfallback[Fake\typescriptprefix{\typescriptone}Caps] [\typescriptprefix{\typescriptone}Widened] [0x0000-0xFFFF] [\s!rscale=0.85,method=uppercase]
- \definefontsynonym [\typescriptprefix{\typescriptone}Caps] [\s!file:\typescriptprefix{n:plex\typescriptone}-regular] [\s!fallbacks=Fake\typescriptprefix{\typescriptone}Caps]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:plex\typescriptone}-regular] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Italic] [\s!file:\typescriptprefix{n:plex\typescriptone}-italic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone}-bold] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!BoldItalic] [\s!file:\typescriptprefix{n:plex\typescriptone}-bolditalic] [\s!features=\typescriptprefix{f:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}Widened] [\s!file:\typescriptprefix{n:plex\typescriptone}-regular] [\s!features=\typescriptprefix{f:scplex\typescriptone}]
+ \edefinefontfallback[Fake\typescriptprefix{\typescriptone}Caps] [\typescriptprefix{\typescriptone}Widened] [0x0000-0xFFFF] [\s!rscale=0.85,method=uppercase]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}Caps] [\s!file:\typescriptprefix{n:plex\typescriptone}-regular] [\s!fallbacks=Fake\typescriptprefix{\typescriptone}Caps]
\stoptypescript
% narrow
\starttypescript [\s!sans,\s!serif,\s!mono] [ibmplexnarrow-thin] [\s!name]
\setups[\s!font:\s!fallback:\typescriptone]
- \definefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-thin] [\s!features=\typescriptprefix{f:narrowplex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Italic] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-thinitalic] [\s!features=\typescriptprefix{f:narrowplex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-text] [\s!features=\typescriptprefix{f:narrowplex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!BoldItalic] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-textitalic] [\s!features=\typescriptprefix{f:narrowplex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}Widened] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-thin] [\s!features=\typescriptprefix{f:scnarrowplex\typescriptone}]
- \definefontfallback[Fake\typescriptprefix{\typescriptone}Caps] [\typescriptprefix{\typescriptone}Widened] [0x0000-0xFFFF] [\s!rscale=0.85,method=uppercase]
- \definefontsynonym [\typescriptprefix{\typescriptone}Caps] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-thin] [\s!fallbacks=Fake\typescriptprefix{\typescriptone}Caps]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-thin] [\s!features=\typescriptprefix{f:narrowplex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Italic] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-thinitalic] [\s!features=\typescriptprefix{f:narrowplex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-text] [\s!features=\typescriptprefix{f:narrowplex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!BoldItalic] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-textitalic] [\s!features=\typescriptprefix{f:narrowplex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}Widened] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-thin] [\s!features=\typescriptprefix{f:scnarrowplex\typescriptone}]
+ \edefinefontfallback[Fake\typescriptprefix{\typescriptone}Caps] [\typescriptprefix{\typescriptone}Widened] [0x0000-0xFFFF] [\s!rscale=0.85,method=uppercase]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}Caps] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-thin] [\s!fallbacks=Fake\typescriptprefix{\typescriptone}Caps]
\stoptypescript
\starttypescript [\s!sans,\s!serif,\s!mono] [ibmplexnarrow-extralight] [\s!name]
\setups[\s!font:\s!fallback:\typescriptone]
- \definefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-extralight] [\s!features=\typescriptprefix{f:narrowplex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Italic] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-extralightitalic] [\s!features=\typescriptprefix{f:narrowplex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-medium] [\s!features=\typescriptprefix{f:narrowplex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!BoldItalic] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-mediumitalic] [\s!features=\typescriptprefix{f:narrowplex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}Widened] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-extralight] [\s!features=\typescriptprefix{f:scnarrowplex\typescriptone}]
- \definefontfallback[Fake\typescriptprefix{\typescriptone}Caps] [\typescriptprefix{\typescriptone}Widened] [0x0000-0xFFFF] [\s!rscale=0.85,method=uppercase]
- \definefontsynonym [\typescriptprefix{\typescriptone}Caps] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-extralight] [\s!fallbacks=Fake\typescriptprefix{\typescriptone}Caps]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-extralight] [\s!features=\typescriptprefix{f:narrowplex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Italic] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-extralightitalic] [\s!features=\typescriptprefix{f:narrowplex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-medium] [\s!features=\typescriptprefix{f:narrowplex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!BoldItalic] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-mediumitalic] [\s!features=\typescriptprefix{f:narrowplex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}Widened] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-extralight] [\s!features=\typescriptprefix{f:scnarrowplex\typescriptone}]
+ \edefinefontfallback[Fake\typescriptprefix{\typescriptone}Caps] [\typescriptprefix{\typescriptone}Widened] [0x0000-0xFFFF] [\s!rscale=0.85,method=uppercase]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}Caps] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-extralight] [\s!fallbacks=Fake\typescriptprefix{\typescriptone}Caps]
\stoptypescript
\starttypescript [\s!sans,\s!serif,\s!mono] [ibmplexnarrow-light] [\s!name]
\setups[\s!font:\s!fallback:\typescriptone]
- \definefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-light] [\s!features=\typescriptprefix{f:narrowplex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Italic] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-lightitalic] [\s!features=\typescriptprefix{f:narrowplex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-semibold] [\s!features=\typescriptprefix{f:narrowplex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!BoldItalic] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-semibolditalic] [\s!features=\typescriptprefix{f:narrowplex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}Widened] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-light] [\s!features=\typescriptprefix{f:scnarrowplex\typescriptone}]
- \definefontfallback[Fake\typescriptprefix{\typescriptone}Caps] [\typescriptprefix{\typescriptone}Widened] [0x0000-0xFFFF] [\s!rscale=0.85,method=uppercase]
- \definefontsynonym [\typescriptprefix{\typescriptone}Caps] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-light] [\s!fallbacks=Fake\typescriptprefix{\typescriptone}Caps]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-light] [\s!features=\typescriptprefix{f:narrowplex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Italic] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-lightitalic] [\s!features=\typescriptprefix{f:narrowplex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-semibold] [\s!features=\typescriptprefix{f:narrowplex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!BoldItalic] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-semibolditalic] [\s!features=\typescriptprefix{f:narrowplex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}Widened] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-light] [\s!features=\typescriptprefix{f:scnarrowplex\typescriptone}]
+ \edefinefontfallback[Fake\typescriptprefix{\typescriptone}Caps] [\typescriptprefix{\typescriptone}Widened] [0x0000-0xFFFF] [\s!rscale=0.85,method=uppercase]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}Caps] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-light] [\s!fallbacks=Fake\typescriptprefix{\typescriptone}Caps]
\stoptypescript
\starttypescript [\s!sans,\s!serif,\s!mono] [ibmplexnarrow] [\s!name]
\setups[\s!font:\s!fallback:\typescriptone]
- \definefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-regular] [\s!features=\typescriptprefix{f:narrowplex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Italic] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-italic] [\s!features=\typescriptprefix{f:narrowplex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-bold] [\s!features=\typescriptprefix{f:narrowplex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!BoldItalic] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-bolditalic] [\s!features=\typescriptprefix{f:narrowplex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}Widened] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-regular] [\s!features=\typescriptprefix{f:scnarrowplex\typescriptone}]
- \definefontfallback[Fake\typescriptprefix{\typescriptone}Caps] [\typescriptprefix{\typescriptone}Widened] [0x0000-0xFFFF] [\s!rscale=0.85,method=uppercase]
- \definefontsynonym [\typescriptprefix{\typescriptone}Caps] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-regular] [\s!fallbacks=Fake\typescriptprefix{\typescriptone}Caps]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-regular] [\s!features=\typescriptprefix{f:narrowplex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Italic] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-italic] [\s!features=\typescriptprefix{f:narrowplex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-bold] [\s!features=\typescriptprefix{f:narrowplex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!BoldItalic] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-bolditalic] [\s!features=\typescriptprefix{f:narrowplex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}Widened] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-regular] [\s!features=\typescriptprefix{f:scnarrowplex\typescriptone}]
+ \edefinefontfallback[Fake\typescriptprefix{\typescriptone}Caps] [\typescriptprefix{\typescriptone}Widened] [0x0000-0xFFFF] [\s!rscale=0.85,method=uppercase]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}Caps] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-regular] [\s!fallbacks=Fake\typescriptprefix{\typescriptone}Caps]
\stoptypescript
@@ -245,109 +245,109 @@
\definefontfallback [SansHebrewFallbackBold] [SansHebrewBold] [0x0590-0x05ff] [check=yes,force=no]
\starttypescript [\s!sans] [ibmplex-thin] [\s!name]
- \definefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:plex\typescriptone}-thin]
- [\s!features=\typescriptprefix{f:plex\typescriptone},
- \s!fallbacks=\typescriptprefix{tf:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone}-text]
- [\s!features=\typescriptprefix{f:plex\typescriptone},
- \s!fallbacks=\typescriptprefix{bf:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}Hebrew] [\s!file:\typescriptprefix{n:plex\typescriptone-hebrew}-thin]
- [\s!features=hebrew]
- \definefontsynonym [\typescriptprefix{\typescriptone}Hebrew\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone-hebrew}-text]
- [\s!features=hebrew]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:plex\typescriptone}-thin]
+ [\s!features=\typescriptprefix{f:plex\typescriptone},
+ \s!fallbacks=\typescriptprefix{tf:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone}-text]
+ [\s!features=\typescriptprefix{f:plex\typescriptone},
+ \s!fallbacks=\typescriptprefix{bf:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}Hebrew] [\s!file:\typescriptprefix{n:plex\typescriptone-hebrew}-thin]
+ [\s!features=hebrew]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}Hebrew\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone-hebrew}-text]
+ [\s!features=hebrew]
\stoptypescript
\starttypescript [\s!sans] [ibmplex-extralight] [\s!name]
- \definefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:plex\typescriptone}-extralight]
- [\s!features=\typescriptprefix{f:plex\typescriptone},
- \s!fallbacks=\typescriptprefix{tf:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone}-medium]
- [\s!features=\typescriptprefix{f:plex\typescriptone},
- \s!fallbacks=\typescriptprefix{bf:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}Hebrew] [\s!file:\typescriptprefix{n:plex\typescriptone-hebrew}-extralight]
- [\s!features=hebrew]
- \definefontsynonym [\typescriptprefix{\typescriptone}Hebrew\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone-hebrew}-medium]
- [\s!features=hebrew]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:plex\typescriptone}-extralight]
+ [\s!features=\typescriptprefix{f:plex\typescriptone},
+ \s!fallbacks=\typescriptprefix{tf:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone}-medium]
+ [\s!features=\typescriptprefix{f:plex\typescriptone},
+ \s!fallbacks=\typescriptprefix{bf:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}Hebrew] [\s!file:\typescriptprefix{n:plex\typescriptone-hebrew}-extralight]
+ [\s!features=hebrew]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}Hebrew\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone-hebrew}-medium]
+ [\s!features=hebrew]
\stoptypescript
\starttypescript [\s!sans] [ibmplex-light] [\s!name]
- \definefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:plex\typescriptone}-light]
- [\s!features=\typescriptprefix{f:plex\typescriptone},
- \s!fallbacks=\typescriptprefix{tf:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone}-semibold]
- [\s!features=\typescriptprefix{f:plex\typescriptone},
- \s!fallbacks=\typescriptprefix{bf:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}Hebrew] [\s!file:\typescriptprefix{n:plex\typescriptone-hebrew}-light]
- [\s!features=hebrew]
- \definefontsynonym [\typescriptprefix{\typescriptone}Hebrew\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone-hebrew}-semibold]
- [\s!features=hebrew]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:plex\typescriptone}-light]
+ [\s!features=\typescriptprefix{f:plex\typescriptone},
+ \s!fallbacks=\typescriptprefix{tf:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone}-semibold]
+ [\s!features=\typescriptprefix{f:plex\typescriptone},
+ \s!fallbacks=\typescriptprefix{bf:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}Hebrew] [\s!file:\typescriptprefix{n:plex\typescriptone-hebrew}-light]
+ [\s!features=hebrew]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}Hebrew\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone-hebrew}-semibold]
+ [\s!features=hebrew]
\stoptypescript
\starttypescript [\s!sans] [ibmplex] [\s!name]
- \definefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:plex\typescriptone}-regular]
- [\s!features=\typescriptprefix{f:plex\typescriptone},
- \s!fallbacks=\typescriptprefix{tf:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone}-bold]
- [\s!features=\typescriptprefix{f:plex\typescriptone},
- \s!fallbacks=\typescriptprefix{bf:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}Hebrew] [\s!file:\typescriptprefix{n:plex\typescriptone-hebrew}-regular]
- [\s!features=hebrew]
- \definefontsynonym [\typescriptprefix{\typescriptone}Hebrew\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone-hebrew}-bold]
- [\s!features=hebrew]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:plex\typescriptone}-regular]
+ [\s!features=\typescriptprefix{f:plex\typescriptone},
+ \s!fallbacks=\typescriptprefix{tf:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone}-bold]
+ [\s!features=\typescriptprefix{f:plex\typescriptone},
+ \s!fallbacks=\typescriptprefix{bf:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}Hebrew] [\s!file:\typescriptprefix{n:plex\typescriptone-hebrew}-regular]
+ [\s!features=hebrew]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}Hebrew\s!Bold] [\s!file:\typescriptprefix{n:plex\typescriptone-hebrew}-bold]
+ [\s!features=hebrew]
\stoptypescript
% narrow
\starttypescript [\s!sans] [ibmplexnarrow-thin] [\s!name]
- \definefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-thin]
- [\s!features=\typescriptprefix{f:narrowplex\typescriptone},
- \s!fallbacks=\typescriptprefix{tf:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-text]
- [\s!features=\typescriptprefix{f:narrowplex\typescriptone},
- \s!fallbacks=\typescriptprefix{bf:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}Hebrew] [\s!file:\typescriptprefix{n:narrowplex\typescriptone-hebrew}-thin]
- [\s!features=hebrew]
- \definefontsynonym [\typescriptprefix{\typescriptone}Hebrew\s!Bold] [\s!file:\typescriptprefix{n:narrowplex\typescriptone-hebrew}-text]
- [\s!features=hebrew]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-thin]
+ [\s!features=\typescriptprefix{f:narrowplex\typescriptone},
+ \s!fallbacks=\typescriptprefix{tf:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-text]
+ [\s!features=\typescriptprefix{f:narrowplex\typescriptone},
+ \s!fallbacks=\typescriptprefix{bf:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}Hebrew] [\s!file:\typescriptprefix{n:narrowplex\typescriptone-hebrew}-thin]
+ [\s!features=hebrew]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}Hebrew\s!Bold] [\s!file:\typescriptprefix{n:narrowplex\typescriptone-hebrew}-text]
+ [\s!features=hebrew]
\stoptypescript
\starttypescript [\s!sans] [ibmplexnarrow-extralight] [\s!name]
- \definefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-extralight]
- [\s!features=\typescriptprefix{f:narrowplex\typescriptone},
- \s!fallbacks=\typescriptprefix{tf:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-medium]
- [\s!features=\typescriptprefix{f:narrowplex\typescriptone},
- \s!fallbacks=\typescriptprefix{bf:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}Hebrew] [\s!file:\typescriptprefix{n:narrowplex\typescriptone-hebrew}-extralight]
- [\s!features=hebrew]
- \definefontsynonym [\typescriptprefix{\typescriptone}Hebrew\s!Bold] [\s!file:\typescriptprefix{n:narrowplex\typescriptone-hebrew}-medium]
- [\s!features=hebrew]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-extralight]
+ [\s!features=\typescriptprefix{f:narrowplex\typescriptone},
+ \s!fallbacks=\typescriptprefix{tf:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-medium]
+ [\s!features=\typescriptprefix{f:narrowplex\typescriptone},
+ \s!fallbacks=\typescriptprefix{bf:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}Hebrew] [\s!file:\typescriptprefix{n:narrowplex\typescriptone-hebrew}-extralight]
+ [\s!features=hebrew]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}Hebrew\s!Bold] [\s!file:\typescriptprefix{n:narrowplex\typescriptone-hebrew}-medium]
+ [\s!features=hebrew]
\stoptypescript
\starttypescript [\s!sans] [ibmplexnarrow-light] [\s!name]
- \definefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-light]
- [\s!features=\typescriptprefix{f:narrowplex\typescriptone},
- \s!fallbacks=\typescriptprefix{tf:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-semibold]
- [\s!features=\typescriptprefix{f:narrowplex\typescriptone},
- \s!fallbacks=\typescriptprefix{bf:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}Hebrew] [\s!file:\typescriptprefix{n:narrowplex\typescriptone-hebrew}-light]
- [\s!features=hebrew]
- \definefontsynonym [\typescriptprefix{\typescriptone}Hebrew\s!Bold] [\s!file:\typescriptprefix{n:narrowplex\typescriptone-hebrew}-semibold]
- [\s!features=hebrew]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-light]
+ [\s!features=\typescriptprefix{f:narrowplex\typescriptone},
+ \s!fallbacks=\typescriptprefix{tf:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-semibold]
+ [\s!features=\typescriptprefix{f:narrowplex\typescriptone},
+ \s!fallbacks=\typescriptprefix{bf:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}Hebrew] [\s!file:\typescriptprefix{n:narrowplex\typescriptone-hebrew}-light]
+ [\s!features=hebrew]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}Hebrew\s!Bold] [\s!file:\typescriptprefix{n:narrowplex\typescriptone-hebrew}-semibold]
+ [\s!features=hebrew]
\stoptypescript
\starttypescript [\s!sans] [ibmplexnarrow] [\s!name]
- \definefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-regular]
- [\s!features=\typescriptprefix{f:narrowplex\typescriptone},
- \s!fallbacks=\typescriptprefix{tf:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-bold]
- [\s!features=\typescriptprefix{f:narrowplex\typescriptone},
- \s!fallbacks=\typescriptprefix{bf:plex\typescriptone}]
- \definefontsynonym [\typescriptprefix{\typescriptone}Hebrew] [\s!file:\typescriptprefix{n:narrowplex\typescriptone-hebrew}-regular]
- [\s!features=hebrew]
- \definefontsynonym [\typescriptprefix{\typescriptone}Hebrew\s!Bold] [\s!file:\typescriptprefix{n:narrowplex\typescriptone-hebrew}-bold]
- [\s!features=hebrew]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-regular]
+ [\s!features=\typescriptprefix{f:narrowplex\typescriptone},
+ \s!fallbacks=\typescriptprefix{tf:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}\s!Bold] [\s!file:\typescriptprefix{n:narrowplex\typescriptone}-bold]
+ [\s!features=\typescriptprefix{f:narrowplex\typescriptone},
+ \s!fallbacks=\typescriptprefix{bf:plex\typescriptone}]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}Hebrew] [\s!file:\typescriptprefix{n:narrowplex\typescriptone-hebrew}-regular]
+ [\s!features=hebrew]
+ \edefinefontsynonym [\typescriptprefix{\typescriptone}Hebrew\s!Bold] [\s!file:\typescriptprefix{n:narrowplex\typescriptone-hebrew}-bold]
+ [\s!features=hebrew]
\stoptypescript
% The main definition, inspired by discussion at the 2018 ConTeXt meeting after a talk by Taco. Here
diff --git a/tex/context/interface/mkii/keys-de.xml b/tex/context/interface/mkii/keys-de.xml
index 573770eef..701dc246b 100644
--- a/tex/context/interface/mkii/keys-de.xml
+++ b/tex/context/interface/mkii/keys-de.xml
@@ -590,6 +590,7 @@
<cd:variable name='understrike' value='understrike'/>
<cd:variable name='understrikes' value='understrikes'/>
<cd:variable name='unframed' value='unframed'/>
+ <cd:variable name='unicode' value='unicode'/>
<cd:variable name='unit' value='einheit'/>
<cd:variable name='units' value='einheiten'/>
<cd:variable name='unknown' value='unbekannt'/>
diff --git a/tex/context/interface/mkii/keys-en.xml b/tex/context/interface/mkii/keys-en.xml
index a3606e38b..686a4dc06 100644
--- a/tex/context/interface/mkii/keys-en.xml
+++ b/tex/context/interface/mkii/keys-en.xml
@@ -590,6 +590,7 @@
<cd:variable name='understrike' value='understrike'/>
<cd:variable name='understrikes' value='understrikes'/>
<cd:variable name='unframed' value='unframed'/>
+ <cd:variable name='unicode' value='unicode'/>
<cd:variable name='unit' value='unit'/>
<cd:variable name='units' value='units'/>
<cd:variable name='unknown' value='unknown'/>
diff --git a/tex/context/interface/mkii/keys-nl.xml b/tex/context/interface/mkii/keys-nl.xml
index 1104e14c1..06df09bc5 100644
--- a/tex/context/interface/mkii/keys-nl.xml
+++ b/tex/context/interface/mkii/keys-nl.xml
@@ -590,6 +590,7 @@
<cd:variable name='understrike' value='understrike'/>
<cd:variable name='understrikes' value='understrikes'/>
<cd:variable name='unframed' value='unframed'/>
+ <cd:variable name='unicode' value='unicode'/>
<cd:variable name='unit' value='eenheid'/>
<cd:variable name='units' value='eenheden'/>
<cd:variable name='unknown' value='onbekend'/>
diff --git a/tex/context/interface/mkiv/i-context.pdf b/tex/context/interface/mkiv/i-context.pdf
index 710c2b708..1c790c10b 100644
--- a/tex/context/interface/mkiv/i-context.pdf
+++ b/tex/context/interface/mkiv/i-context.pdf
Binary files differ
diff --git a/tex/context/interface/mkiv/i-readme.pdf b/tex/context/interface/mkiv/i-readme.pdf
index c9466e104..d713701b0 100644
--- a/tex/context/interface/mkiv/i-readme.pdf
+++ b/tex/context/interface/mkiv/i-readme.pdf
Binary files differ
diff --git a/tex/context/modules/common/s-abbreviations-logos.tex b/tex/context/modules/common/s-abbreviations-logos.tex
index 00719a668..49a30451c 100644
--- a/tex/context/modules/common/s-abbreviations-logos.tex
+++ b/tex/context/modules/common/s-abbreviations-logos.tex
@@ -24,6 +24,7 @@
\logo [MKCI] {MkCI}
\logo [MPII] {MpII}
\logo [MPIV] {MpIV}
+\logo [LMTX] {lmtx}
\logo [ACROBAT] {Acro\-bat}
\logo [AFM] {afm}
@@ -37,6 +38,7 @@
\logo [APA] {apa}
\logo [API] {api}
\logo [ARABTEX] {Arab\TeXsuffix}
+\logo [ARM] {arm}
\logo [ASCII] {ascii}
\logo [ASCIIMATH] {AsciiMath}
\logo [ASCIITEX] {ascii\TeXsuffix}
@@ -53,6 +55,7 @@
\logo [CJK] {cjk}
\logo [CLD] {cld}
\logo [CLD] {cld}
+\logo [CMAKE] {cmake}
\logo [CMR] {cmr}
\logo [CMYK] {cmyk}
\logo [CNC] {cnc}
@@ -67,11 +70,12 @@
\logo [CTXTOOLS] {ctxtools}
\logo [CWEB] {cweb}
\logo [DAC] {dac}
+\logo [DARWIN] {Darwin}
\logo [DECTEN] {dec-10}
\logo [DISTILLER] {distiller}
\logo [DNA] {dna}
\logo [DPI] {dpi}
-\logo [DRATEX] {Dra\TeXsuffix}
+%logo [DRATEX] {Dra\TeXsuffix}
\logo [DSC] {dsc}
\logo [DTD] {dtd}
\logo [DTK] {dtk}
@@ -86,7 +90,6 @@
\logo [DVISCR] {dviscr}
\logo [DVIWINDO] {dviwindo}
\logo [EBCDIC] {ebcdic}
-\logo [EU] {eu}
\logo [EC] {ec}
\logo [EIFFEL] {Eiffel}
\logo [EMACS] {emacs}
@@ -96,6 +99,7 @@
\logo [EPS] {eps}
\logo [EPUB] {ePub}
\logo [ETEX] {\eTeX}
+\logo [EU] {eu}
\logo [EUROBACHOTEX] {EuroBacho\TeXsuffix}
\logo [EUROMATH] {EuroMath}
\logo [EUROTEX] {Euro\TeXsuffix}
@@ -151,21 +155,21 @@
\logo [KVM] {kvm}
\logo [LAMSTEX] {\LamSTeX}
\logo [LATEX] {\LaTeX}
-\logo [LATEXTE] {\LaTeX2e}
-\logo [LATEXTN] {\LaTeX2.09}
+%logo [LATEXTE] {\LaTeX2e}
+%logo [LATEXTN] {\LaTeX2.09}
\logo [LCD] {lcd}
\logo [LINUX] {linux}
\logo [LISP] {Lisp}
\logo [LMX] {lmx}
-\logo [LMTX] {lmtx}
\logo [LPEG] {lpeg}
\logo [LUA] {Lua}
\logo [LUAJIT] {LuaJIT}
\logo [LUAJITTEX] {Luajit\TeXsuffix}
+\logo [LUAMETATEX] {\Lua Meta\TeXsuffix}
\logo [LUATEX] {Lua\TeXsuffix}
\logo [LUATOOLS] {luatools}
\logo [MACOSX] {MacOSX}
-\logo [MACROTEX] {Macro\TeXsuffix}
+%logo [MACROTEX] {Macro\TeXsuffix}
\logo [MAKEMPY] {MakeMPY}
\logo [MAPPING] {map}
\logo [MAPS] {Maps}
@@ -188,25 +192,26 @@
\logo [MPS] {mps}
\logo [MPTOPDF] {mptopdf}
\logo [MSDOS] {msdos}
+\logo [MSEXCEL] {MS~Excel}
\logo [MSWINDOWS] {MS~Windows}
\logo [MSWORD] {MS~Word}
-\logo [MSEXCEL] {MS~Excel}
\logo [MTXRUN] {mtxrun}
\logo [MTXTOOLS] {mtxtools}
\logo [MYSQL] {MySQL}
\logo [NETPBM] {NetPBM}
+\logo [NGINX] {nginx}
\logo [NTG] {ntg}
\logo [NTS] {nts}
-\logo [NGINX] {nginx}
\logo [OFM] {ofm}
\logo [OMEGA] {Omega}
+\logo [OPENBSD] {OpenBSD}
\logo [OPENMATH] {OpenMath}
\logo [OPENTYPE] {OpenType}
\logo [OPI] {opi}
+\logo [OSX] {os-x}
\logo [OTEX] {Oriental \TeXsuffix}
\logo [OTF] {otf}
\logo [OTP] {otp}
-\logo [OSX] {os-x}
\logo [OVF] {ovf}
\logo [PASCAL] {Pascal}
\logo [PCTEX] {pc\TeXsuffix}
@@ -243,8 +248,8 @@
\logo [RELAXNG] {Relax\kern.125emNG}
\logo [RGB] {rgb}
\logo [RLXTOOLS] {rlxtools}
-\logo [RUBY] {Ruby}
\logo [RSYNC] {Rsync}
+\logo [RUBY] {Ruby}
\logo [SCITE] {SciTE}
\logo [SGML] {sgml}
\logo [SI] {si}
@@ -317,12 +322,12 @@
\logo [WEBC] {web2c}
\logo [WIKI] {Wiki}
\logo [WINDOWS] {Windows}
-\logo [WINNT] {WinNT}
-\logo [WINNX] {Win9x}
+%logo [WINNT] {WinNT}
+%logo [WINNX] {Win9x}
\logo [WTHREEC] {W3C}
\logo [WWW] {www}
\logo [WYSIWYG] {wysiwyg}
-\logo [XDVI] {Xdvi}
+%logo [XDVI] {Xdvi}
\logo [XETEX] {\XeTeX}
\logo [XFDF] {xfdf}
\logo [XHTML] {xhtml}
@@ -331,7 +336,7 @@
\logo [XML] {xml}
\logo [XMLTOOLS] {xmltools}
\logo [XPATH] {xpath}
-\logo [XPDFETEX] {xpdfe\TeXsuffix}
+%logo [XPDFETEX] {xpdfe\TeXsuffix}
\logo [XSL] {xsl}
\logo [XSLFO] {xsl-fo}
\logo [XSLT] {xslt}
diff --git a/tex/context/modules/mkiv/m-chart.lua b/tex/context/modules/mkiv/m-chart.lua
index cde563fb3..7973640a7 100644
--- a/tex/context/modules/mkiv/m-chart.lua
+++ b/tex/context/modules/mkiv/m-chart.lua
@@ -864,8 +864,8 @@ local function getchart(settings,forced_x,forced_y,forced_nx,forced_ny)
for i=1,#data do
local cell = data[i]
if not autofocus or autofocus[cell.name] then -- offsets probably interfere with autofocus
- local x = cell.x
- local y = cell.y
+ local x = cell.realx -- was bug: .x
+ local y = cell.realy -- was bug: .y
if minx == 0 or x < minx then minx = x end
if miny == 0 or y < miny then miny = y end
if minx == 0 or x > maxx then maxx = x end
diff --git a/tex/context/modules/mkiv/m-punk.mkiv b/tex/context/modules/mkiv/m-punk.mkiv
index 5b8455425..29a6d8cca 100644
--- a/tex/context/modules/mkiv/m-punk.mkiv
+++ b/tex/context/modules/mkiv/m-punk.mkiv
@@ -211,18 +211,18 @@ metapost.characters.flusher = flusher
statistics.register("metapost font generation", function()
local time = statistics.elapsedtime(flusher)
if total > 0 then
- return string.format("%i glyphs, %.3f seconds runtime, %0.3f glyphs/second", total, time, total/time)
+ return string.format("%i glyphs, %s seconds runtime, %0.3f glyphs/second", total, time, total/tonumber(time))
else
- return string.format("%i glyphs, %.3f seconds runtime", total, time)
+ return string.format("%i glyphs, %s seconds runtime", total, time)
end
end)
statistics.register("metapost font loading",function()
local time = statistics.elapsedtime(metapost.characters)
if variants > 0 then
- return string.format("%.3f seconds, %i instances, %0.3f instances/second", time, variants, variants/time)
+ return string.format("%s seconds, %i instances, %0.3f instances/second", time, variants, variants/tonumber(time))
else
- return string.format("%.3f seconds, %i instances", time, variants)
+ return string.format("%s seconds, %i instances", time, variants)
end
end)
\stopluacode
diff --git a/tex/context/sample/third/aristotle-grc.tex b/tex/context/sample/third/aristotle-grc.tex
new file mode 100644
index 000000000..85d774f23
--- /dev/null
+++ b/tex/context/sample/third/aristotle-grc.tex
@@ -0,0 +1,13 @@
+\startlanguage[grc]
+Λόγος δέ ἐστι φωνὴ σημαντική, ἧς τῶν μερῶν τι σημαντικόν ἐστι
+κεχωρισμένον, ὡς φάσις ἀλλ᾽ οὐχ ὡς κατάφασις. λέγω δέ, οἷον ἄνθρωπος
+σημαίνει τι, ἀλλ᾽ οὐχ ὅτι ἔστιν ἢ οὐκ ἔστιν (ἀλλ᾽ ἔσται κατάφασις ἢ
+ἀπόφασις ἐάν τι προστεθῇ)· ἀλλ᾽ οὐχ ἡ τοῦ ἀνθρώπου συλλαβὴ μία· οὐδὲ
+γὰρ ἐν τῷ μῦς τὸ υς σημαντικόν, ἀλλὰ φωνή ἐστι νῦν μόνον. ἐν δὲ τοῖς
+διπλοῖς σημαίνει μέν, ἀλλ᾽ οὐ καθ᾽ αὑτό, ὥσπερ εἴρηται. ἔστι δὲ λόγος
+ἅπας μὲν σημαντικός, οὐχ ὡς ὄργανον δέ, ἀλλ᾽ ὥσπερ εἴρηται κατὰ
+συνθήκην· ἀποφαντικὸς δὲ οὐ πᾶς, ἀλλ᾽ ἐν ᾧ τὸ ἀληθεύειν ἢ ψεύδεσθαι
+ὑπάρχει· οὐκ ἐν ἅπασι δὲ ὑπάρχει, οἷον ἡ εὐχὴ λόγος μέν, ἀλλ᾽ οὔτ᾽
+ἀληθὴς οὔτε ψευδής. οἱ μὲν οὖν ἄλλοι ἀφείσθωσαν, —ῥητορικῆς γὰρ ἢ
+ποιητικῆς οἰκειοτέρα ἡ σκέψις,— ὁ δὲ ἀποφαντικὸς τῆς νῦν θεωρίας.
+\stoplanguage
diff --git a/tex/context/sample/third/capek-cz.tex b/tex/context/sample/third/capek-cz.tex
new file mode 100644
index 000000000..8083d7152
--- /dev/null
+++ b/tex/context/sample/third/capek-cz.tex
@@ -0,0 +1,13 @@
+Tak vám jednou byl jeden chudý pán neboli člověk, on se vlastně jmenoval
+František Král, ale tak mu říkali jenom tehdy, když ho sebral strážník a
+dovedl ho na komisařství pro potulku, kde ho zapsali do takové tlusté knihy
+a nechali ho přespat na pryčně a ráno ho zase poslali dál; na policii mu
+tedy říkali František Král, ale ostatní lidé ho jmenovali všelijak jinak:
+ten vandrák, ten šupák, ten tulák, ten pobuda, ten lajdák, ten otrapa, ten
+hadrník, ten trhan, ten obejda, ten lenoch, ten chudák, ten jindyvyjduum,
+ten člověk, ten kdovíkdo, ten poběhlík, ten krajánek, ten štvanec, ten
+vošlapa, ten revertent, ten vagabund, ten darmošlap, ten budižkničemu, ten
+hlad, ten hunt, ten holota a ještě mnoho jiných jmen mu dávali; kdyby každé
+to názvisko platilo aspoň korunu, mohl by si za ně koupit žluté boty a možná
+že i klobouk, ale takhle si za to nekoupil nic a měl jenom to, co mu lidé
+dali.
diff --git a/tex/context/sample/third/capek-vlnka-cz.tex b/tex/context/sample/third/capek-vlnka-cz.tex
new file mode 100644
index 000000000..9fede2334
--- /dev/null
+++ b/tex/context/sample/third/capek-vlnka-cz.tex
@@ -0,0 +1,13 @@
+Tak vám jednou byl jeden chudý pán neboli člověk, on se vlastně jmenoval
+František Král, ale tak mu říkali jenom tehdy, když ho sebral strážník
+a~dovedl ho na komisařství pro potulku, kde ho zapsali do takové tlusté knihy
+a~nechali ho přespat na pryčně a~ráno ho zase poslali dál; na policii mu
+tedy říkali František Král, ale ostatní lidé ho jmenovali všelijak jinak:
+ten vandrák, ten šupák, ten tulák, ten pobuda, ten lajdák, ten otrapa, ten
+hadrník, ten trhan, ten obejda, ten lenoch, ten chudák, ten jindyvyjduum,
+ten člověk, ten kdovíkdo, ten poběhlík, ten krajánek, ten štvanec, ten
+vošlapa, ten revertent, ten vagabund, ten darmošlap, ten budižkničemu, ten
+hlad, ten hunt, ten holota a~ještě mnoho jiných jmen mu dávali; kdyby každé
+to názvisko platilo aspoň korunu, mohl by si za ně koupit žluté boty a~možná
+že i~klobouk, ale takhle si za to nekoupil nic a~měl jenom to, co mu lidé
+dali.
diff --git a/tex/context/sample/third/dequincey.tex b/tex/context/sample/third/dequincey.tex
new file mode 100644
index 000000000..a1070b562
--- /dev/null
+++ b/tex/context/sample/third/dequincey.tex
@@ -0,0 +1,5 @@
+For if once a man indulges himself in murder, very soon he comes to
+think little of robbing; and from robbing he comes next to drinking and
+Sabbath--breaking, and from that to incivility and procrastination.
+Once begin upon this downward path, you never know where you are to
+stop.
diff --git a/tex/context/sample/third/dyrynk-cz.tex b/tex/context/sample/third/dyrynk-cz.tex
new file mode 100644
index 000000000..e12a228b9
--- /dev/null
+++ b/tex/context/sample/third/dyrynk-cz.tex
@@ -0,0 +1,22 @@
+Čeho jsem si zvlášť všímal při prohlížení knih, je typografické jejich
+zhotovení, technické provedení knihtiskařem, které po mém soudu je základem
+dobré knižní úpravy. A tu nelze upřít, že řemeslná stránka je dosud stránkou
+slabou většiny našich knih. Často až překvapí rozpor mezi péčí, kterou
+věnoval umělec výzdobě knihy, a ledabylostí, s jakou ji tiskárna zhotovila.
+Bývá to podivná harmonie: výzdoba umělecká a sazba i tisk jako denních
+novin. Nejsou to malé závody, jichž výrobkům lze vytknouti tuto řemeslnou
+chybu, i přední veliké tiskárny zhotovují takto >>krásné<< knihy. Stačí
+prohlédnouti si podrobněji reprodukce v tomto díle, abychom se přesvědčili,
+že to tvrzení není přehnané.
+
+Přece však lze pozorovati potěšitelný obrat k lepšímu: některé české
+knihtiskárny se chlubí už správně vysazenými a dobře vytištěnými knihami.
+Sice dosud jest málo impressí, které takto jeví úctu a vážnost k svému
+černému umění, obracejíce knihtisk k jeho staré lásce, knize, a věnujíce
+její vkusné úpravě čas, píči a píli; na prstech jedné ruky by je spočetl.
+Nepochybuji však, že jich přibude, vždyť ničím nemůže se knihtiskárna
+lépe doporučiti než svojí firmou na dokonale, krásně upravené knize, která
+je rozkoší oku a potěšením duši, a ještě po letech a desetiletích, kdy
+dávno upadnou v zapomnění drobné akcidence, zůstane v knihovnách jako svědek
+odborné vyspělosti knihtiskárny, schopnosti jejích pracovníků
+a prozíravosti i vkusu principála nebo řiditele závodu.
diff --git a/tex/context/sample/third/dyrynk-vlnka-cz.tex b/tex/context/sample/third/dyrynk-vlnka-cz.tex
new file mode 100644
index 000000000..1d4df1e49
--- /dev/null
+++ b/tex/context/sample/third/dyrynk-vlnka-cz.tex
@@ -0,0 +1,23 @@
+
+Čeho jsem si zvlášť všímal při prohlížení knih, je typografické jejich
+zhotovení, technické provedení knihtiskařem, které po mém soudu je základem
+dobré knižní úpravy. A~tu nelze upřít, že řemeslná stránka je dosud stránkou
+slabou většiny našich knih. Často až překvapí rozpor mezi péčí, kterou
+věnoval umělec výzdobě knihy, a~ledabylostí, s~jakou ji tiskárna zhotovila.
+Bývá to podivná harmonie: výzdoba umělecká a~sazba i~tisk jako denních
+novin. Nejsou to malé závody, jichž výrobkům lze vytknouti tuto řemeslnou
+chybu, i~přední veliké tiskárny zhotovují takto >>krásné<< knihy. Stačí
+prohlédnouti si podrobněji reprodukce v~tomto díle, abychom se přesvědčili,
+že to tvrzení není přehnané.
+
+Přece však lze pozorovati potěšitelný obrat k~lepšímu: některé české
+knihtiskárny se chlubí už správně vysazenými a~dobře vytištěnými knihami.
+Sice dosud jest málo impressí, které takto jeví úctu a~vážnost k~svému
+černému umění, obracejíce knihtisk k~jeho staré lásce, knize, a~věnujíce
+její vkusné úpravě čas, píči a~píli; na prstech jedné ruky by je spočetl.
+Nepochybuji však, že jich přibude, vždyť ničím nemůže se knihtiskárna
+lépe doporučiti než svojí firmou na dokonale, krásně upravené knize, která
+je rozkoší oku a~potěšením duši, a~ještě po letech a~desetiletích, kdy
+dávno upadnou v~zapomnění drobné akcidence, zůstane v~knihovnách jako svědek
+odborné vyspělosti knihtiskárny, schopnosti jejích pracovníků
+a~prozíravosti i~vkusu principála nebo řiditele závodu.
diff --git a/tex/context/sample/third/kollar-cz.tex b/tex/context/sample/third/kollar-cz.tex
new file mode 100644
index 000000000..5a4f63695
--- /dev/null
+++ b/tex/context/sample/third/kollar-cz.tex
@@ -0,0 +1,31 @@
+
+Aj zde leží zem ta před okem mým slzy ronícím,
+někdy kolébka, nyní národu mého rakev.
+Stoj noho! posvátná místa jsou, kamkoli kráčíš,
+k obloze, Tatry synu, vznes se vyvýše pohled,
+neb raději k velikému prichyl tomu tam se dubisku,
+jenž vzdoruje zhoubným až dosaváde časům.
+Však času ten horší je člověk, jenž berlu železnou
+v těchto krajích na tvou, Slavie, šíji chopil.
+Horší, nežli divé války, hromu, ohně divější,
+zaslepenec na své když zlobu plémě kydá.
+Ó věkové dávní, jako noc vůkol mne ležící,
+ó krajino, všeliké slávy i hanby obraz!
+Od Labe zrádného k rovinám až Visly nevěrné,
+od Dunaje k hltným Baltu celého pěnám:
+Krásnohlasy zmužilých Slavjanů kde se někdy ozýval,
+aj oněmělť už, byv k ourazu zášti, jazyk.
+A kdo se loupeže té, volající vzhůru, dopustil?
+Kdo zhanobil v jednom národu lidstvo celé?
+Zardi se závistná Teutonie, sousedo Slávy,
+tvé vin těchto počet spáchaly někdy ruky!
+Neb krve nikde tolik nevylil černidla že žádný
+nepřítel, co vylil k záhubě Slávy Němec.
+Sám svobody kdo hoden, svobodu zná vážiti každou,
+ten kdo do pout jímá otroky, sám je otrok.
+Nechť ruky, nechť by jazyk v okovy své vázal otrocké,
+jedno to, neb nezná šetřiti práva jiných.
+Ten, kdo trůny bořil, lidskou krev darmo vyléval,
+po světě nešťastnou války pochodni nosil:
+ten porobu slušnou, buď Goth, buď Skytha zasloužil,
+ne kdo divé chválil příkladem ordě pokoj.
diff --git a/tex/context/sample/third/kollar-vlnka-cz.tex b/tex/context/sample/third/kollar-vlnka-cz.tex
new file mode 100644
index 000000000..01e815e74
--- /dev/null
+++ b/tex/context/sample/third/kollar-vlnka-cz.tex
@@ -0,0 +1,30 @@
+Aj zde leží zem ta před okem mým slzy ronícím,
+někdy kolébka, nyní národu mého rakev.
+Stoj noho! posvátná místa jsou, kamkoli kráčíš,
+k~obloze, Tatry synu, vznes se vyvýše pohled,
+neb raději k~velikému prichyl tomu tam se dubisku,
+jenž vzdoruje zhoubným až dosaváde časům.
+Však času ten horší je člověk, jenž berlu železnou
+v~těchto krajích na tvou, Slavie, šíji chopil.
+Horší, nežli divé války, hromu, ohně divější,
+zaslepenec na své když zlobu plémě kydá.
+Ó věkové dávní, jako noc vůkol mne ležící,
+ó krajino, všeliké slávy i~hanby obraz!
+Od Labe zrádného k~rovinám až Visly nevěrné,
+od Dunaje k~hltným Baltu celého pěnám:
+Krásnohlasy zmužilých Slavjanů kde se někdy ozýval,
+aj oněmělť už, byv k~ourazu zášti, jazyk.
+A~kdo se loupeže té, volající vzhůru, dopustil?
+Kdo zhanobil v~jednom národu lidstvo celé?
+Zardi se závistná Teutonie, sousedo Slávy,
+tvé vin těchto počet spáchaly někdy ruky!
+Neb krve nikde tolik nevylil černidla že žádný
+nepřítel, co vylil k~záhubě Slávy Němec.
+Sám svobody kdo hoden, svobodu zná vážiti každou,
+ten kdo do pout jímá otroky, sám je otrok.
+Nechť ruky, nechť by jazyk v~okovy své vázal otrocké,
+jedno to, neb nezná šetřiti práva jiných.
+Ten, kdo trůny bořil, lidskou krev darmo vyléval,
+po světě nešťastnou války pochodni nosil:
+ten porobu slušnou, buď Goth, buď Skytha zasloužil,
+ne kdo divé chválil příkladem ordě pokoj.
diff --git a/tex/context/sample/third/komensky-cz.tex b/tex/context/sample/third/komensky-cz.tex
new file mode 100644
index 000000000..f25bb47d9
--- /dev/null
+++ b/tex/context/sample/third/komensky-cz.tex
@@ -0,0 +1,33 @@
+Nejkrásnějším dílem Božím je svět, všeliké neviditelné Božské věcí viditelné
+ukazující. Nejkrásnější je ale naše duše, jíž je dáno, myšlením zobrazovat
+ve svém nitru svět i věci veškery. Nejkrásnější je řeč, jejíž pomocí
+vmalováváme všeliké obrazy své duše v duši druhého. Nejkrásnější je písmo,
+jímž zachycujeme a natrvalo upevňujeme řeč, samu o sobě prchavou a
+pomíjející, a jímž jako bychom ji zadržovali, aby trvala. Nejkrásnější jsou
+knihy, písmem ladně sestavené, jimiž zpodobenou moudrost posíláme lidem,
+místně či časově vzdáleným, ba dokonce i pozdnímu potomstvu. Nejkrásnějším
+darem Božím je vynález tiskových liter, jimž se knihy nesmírně rychle
+rozmnožují.
+
+Sazeč, maje před sebou kasu, naplněnou kovovými literkami, uloženými v
+přihrádkách, dívá se do rukopisu, postaveného na vidlici tak, aby pohodlně
+viděl, v levé ruce sázítko, pravou rukou vybírá (z přihrádek) literky a
+skládá je do sázítka v slova: když naplní sloupec, přenáší je na desku.
+Jakmile pak je naplněn počet sloupců pro jednu stranu archu, rozdělí je
+příložkami, ováže je a stáhne železnými rámy, aby se nerozpadly; a tím se
+podle svého mínění sví povinnosti zhostil.
+
+A tak tito všichni pracujíce vzájemně vykonávající jakoby hračkou
+podivuhodné dílo, lidem kdysi nepochopitelné, jen když mají všichni to, čeho
+je přitom potření, jednak odborné znalosti zbystřené praxí, jednak vytrvalou
+pozornost a píli. Znalosti: poněvadž třebaže je tiskařství řemeslem, je
+nejsubtilnějším uměním, skládajícím se z přečetných maličkostí, na něž nutno
+dávat dobrý pozor. Pozornost a píli: poněvadž zde, kde se stýká tolik
+maličkostí, velmi snadno se něco přihodí, co by dílo rušilo, kdyby se
+nebdělo.
+
+Tolik ve všeobecnosti o tom, jak se tisknou knihy vůbec. Jestliže by se
+naskytla otázka, jak vznikají knihy dobré, bude třeba říci, že je žádoucí za
+prvé rozumně sepsaný rukopis, hodný světla a nikoli tmy; na druhém místě
+elegantní typy; na třetím čistý papír; na čtvrtém pak pozorná práce, aby vše
+až do poslední čárky bylo zřetelné, rozlišené a správné.
diff --git a/tex/context/sample/third/komensky-vlnka-cz.tex b/tex/context/sample/third/komensky-vlnka-cz.tex
new file mode 100644
index 000000000..17a2ab3f7
--- /dev/null
+++ b/tex/context/sample/third/komensky-vlnka-cz.tex
@@ -0,0 +1,33 @@
+Nejkrásnějším dílem Božím je svět, všeliké neviditelné Božské věcí viditelné
+ukazující. Nejkrásnější je ale naše duše, jíž je dáno, myšlením zobrazovat
+ve svém nitru svět i~věci veškery. Nejkrásnější je řeč, jejíž pomocí
+vmalováváme všeliké obrazy své duše v~duši druhého. Nejkrásnější je písmo,
+jímž zachycujeme a~natrvalo upevňujeme řeč, samu o~sobě prchavou
+a~pomíjející, a~jímž jako bychom ji zadržovali, aby trvala. Nejkrásnější jsou
+knihy, písmem ladně sestavené, jimiž zpodobenou moudrost posíláme lidem,
+místně či časově vzdáleným, ba dokonce i~pozdnímu potomstvu. Nejkrásnějším
+darem Božím je vynález tiskových liter, jimž se knihy nesmírně rychle
+rozmnožují.
+
+Sazeč, maje před sebou kasu, naplněnou kovovými literkami, uloženými
+v~přihrádkách, dívá se do rukopisu, postaveného na vidlici tak, aby pohodlně
+viděl, v~levé ruce sázítko, pravou rukou vybírá (z~přihrádek) literky
+a~skládá je do sázítka v~slova: když naplní sloupec, přenáší je na desku.
+Jakmile pak je naplněn počet sloupců pro jednu stranu archu, rozdělí je
+příložkami, ováže je a~stáhne železnými rámy, aby se nerozpadly; a~tím se
+podle svého mínění sví povinnosti zhostil.
+
+A~tak tito všichni pracujíce vzájemně vykonávající jakoby hračkou
+podivuhodné dílo, lidem kdysi nepochopitelné, jen když mají všichni to, čeho
+je přitom potřebí, jednak odborné znalosti zbystřené praxí, jednak vytrvalou
+pozornost a~píli. Znalosti: poněvadž třebaže je tiskařství řemeslem, je
+nejsubtilnějším uměním, skládajícím se z~přečetných maličkostí, na něž nutno
+dávat dobrý pozor. Pozornost a~píli: poněvadž zde, kde se stýká tolik
+maličkostí, velmi snadno se něco přihodí, co by dílo rušilo, kdyby se
+nebdělo.
+
+Tolik ve všeobecnosti o~tom, jak se tisknou knihy vůbec. Jestliže by se
+naskytla otázka, jak vznikají knihy dobré, bude třeba říci, že je žádoucí za
+prvé rozumně sepsaný rukopis, hodný světla a~nikoli tmy; na druhém místě
+elegantní typy; na třetím čistý papír; na čtvrtém pak pozorná práce, aby vše
+až do poslední čárky bylo zřetelné, rozlišené a~správné.
diff --git a/tex/context/sample/third/krdel-sk.tex b/tex/context/sample/third/krdel-sk.tex
new file mode 100644
index 000000000..2f2395427
--- /dev/null
+++ b/tex/context/sample/third/krdel-sk.tex
@@ -0,0 +1,7 @@
+
+KŔDEĽ ŠŤASTNÝCH ĎATĽOV UČÍ PRI ÚSTÍ VÁHU MĹKVÉHO KOŇA OBHRÝZAŤ KÔRU A ŽRAŤ ČERSTVÉ MÄSO.
+
+Kŕdeľ šťastných ďatľov učí pri ústí Váhu mĺkveho koňa obhrýzať kôru a žrať čerstvé mäso.
+
+0123456789 :;!?()[]\{\} -/--/--- ÖÜŮŘ öüůř
+
diff --git a/tex/context/sample/third/kun-cz.tex b/tex/context/sample/third/kun-cz.tex
new file mode 100644
index 000000000..ee1471c1b
--- /dev/null
+++ b/tex/context/sample/third/kun-cz.tex
@@ -0,0 +1,7 @@
+
+ŽLUŤOUČKÝ KŮŇ ÚPĚL ĎÁBELSKÉ ÓDY,
+
+žluťoučký kůň úpěl ďábelské ódy.
+
+0123456789 :;!?()[]\{\} -/--/--- ŕĺľäöü ŔĹĽÄÖÜ
+
diff --git a/tex/generic/context/luatex/luatex-basics-nod.lua b/tex/generic/context/luatex/luatex-basics-nod.lua
index e22f170ef..879da4bc7 100644
--- a/tex/generic/context/luatex/luatex-basics-nod.lua
+++ b/tex/generic/context/luatex/luatex-basics-nod.lua
@@ -70,81 +70,77 @@ nodes.nodecodes = nodecodes
nodes.glyphcodes = glyphcodes
nodes.disccodes = disccodes
-local flush_node = node.flush_node
-local remove_node = node.remove
-local traverse_id = node.traverse_id
-
nodes.handlers.protectglyphs = node.protect_glyphs -- beware: nodes!
nodes.handlers.unprotectglyphs = node.unprotect_glyphs -- beware: nodes!
-function nodes.remove(head, current, free_too)
- local t = current
- head, current = remove_node(head,current)
- if t then
- if free_too then
- flush_node(t)
- t = nil
- else
- t.next, t.prev = nil, nil
- end
- end
- return head, current, t
-end
-
-function nodes.delete(head,current)
- return nodes.remove(head,current,true)
-end
-
-local getfield = node.getfield
-local setfield = node.setfield
-
-nodes.getfield = getfield
-nodes.setfield = setfield
-
-nodes.getattr = getfield
-nodes.setattr = setfield
-
--- being lazy ... just copy a bunch ... not all needed in generic but we assume
--- nodes to be kind of private anyway
-
-nodes.tostring = node.tostring or tostring
-nodes.copy = node.copy
-nodes.copy_node = node.copy
-nodes.copy_list = node.copy_list
-nodes.delete = node.delete
-nodes.dimensions = node.dimensions
-nodes.end_of_math = node.end_of_math
-nodes.flush_list = node.flush_list
-nodes.flush_node = node.flush_node
-nodes.flush = node.flush_node
-nodes.free = node.free
-nodes.insert_after = node.insert_after
-nodes.insert_before = node.insert_before
-nodes.hpack = node.hpack
-nodes.new = node.new
-nodes.tail = node.tail
-nodes.traverse = node.traverse
-nodes.traverse_id = node.traverse_id
-nodes.slide = node.slide
-nodes.vpack = node.vpack
-
-nodes.first_glyph = node.first_glyph
-nodes.has_glyph = node.has_glyph or node.first_glyph
-
-nodes.current_attr = node.current_attr
-nodes.has_field = node.has_field
-nodes.last_node = node.last_node
-nodes.usedlist = node.usedlist
-nodes.protrusion_skippable = node.protrusion_skippable
-nodes.write = node.write
-
-nodes.has_attribute = node.has_attribute
-nodes.set_attribute = node.set_attribute
-nodes.unset_attribute = node.unset_attribute
-
-nodes.protect_glyphs = node.protect_glyphs
-nodes.unprotect_glyphs = node.unprotect_glyphs
-nodes.mlist_to_hlist = node.mlist_to_hlist
+-- These are now gone in generic as they are context specific.
+
+-- local flush_node = node.flush_node
+-- local remove_node = node.remove
+-- local traverse_id = node.traverse_id
+--
+-- function nodes.remove(head, current, free_too)
+-- local t = current
+-- head, current = remove_node(head,current)
+-- if t then
+-- if free_too then
+-- flush_node(t)
+-- t = nil
+-- else
+-- t.next, t.prev = nil, nil
+-- end
+-- end
+-- return head, current, t
+-- end
+--
+-- function nodes.delete(head,current)
+-- return nodes.remove(head,current,true)
+-- end
+
+----- getfield = node.getfield
+----- setfield = node.setfield
+
+-----.getfield = getfield
+-----.setfield = setfield
+-----.getattr = getfield
+-----.setattr = setfield
+
+-----.tostring = node.tostring or tostring
+-----.copy = node.copy
+-----.copy_node = node.copy
+-----.copy_list = node.copy_list
+-----.delete = node.delete
+-----.dimensions = node.dimensions
+-----.end_of_math = node.end_of_math
+-----.flush_list = node.flush_list
+-----.flush_node = node.flush_node
+-----.flush = node.flush_node
+-----.free = node.free
+-----.insert_after = node.insert_after
+-----.insert_before = node.insert_before
+-----.hpack = node.hpack
+-----.new = node.new
+-----.tail = node.tail
+-----.traverse = node.traverse
+-----.traverse_id = node.traverse_id
+-----.slide = node.slide
+-----.vpack = node.vpack
+
+-----.first_glyph = node.first_glyph
+-----.has_glyph = node.has_glyph or node.first_glyph
+-----.current_attr = node.current_attr
+-----.has_field = node.has_field
+-----.usedlist = node.usedlist
+-----.protrusion_skippable = node.protrusion_skippable
+-----.write = node.write
+
+-----.has_attribute = node.has_attribute
+-----.set_attribute = node.set_attribute
+-----.unset_attribute = node.unset_attribute
+
+-----.protect_glyphs = node.protect_glyphs
+-----.unprotect_glyphs = node.unprotect_glyphs
+-----.mlist_to_hlist = node.mlist_to_hlist
-- in generic code, at least for some time, we stay nodes, while in context
-- we can go nuts (e.g. experimental); this split permits us us keep code
diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua
index d470094fc..6a8a418bd 100644
--- a/tex/generic/context/luatex/luatex-fonts-merged.lua
+++ b/tex/generic/context/luatex/luatex-fonts-merged.lua
@@ -1,6 +1,6 @@
-- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua
-- parent file : c:/data/develop/context/sources/luatex-fonts.lua
--- merge date : 02/14/19 16:57:24
+-- merge date : 04/04/19 13:31:02
do -- begin closure to overcome local limits and interference
@@ -119,8 +119,7 @@ if not FFISUPPORTED then
elseif not ffi.number then
ffi.number=tonumber
end
-if not bit32 then
- bit32=require("l-bit32")
+if LUAVERSION>5.3 then
end
end -- closure
@@ -1045,7 +1044,7 @@ if not modules then modules={} end modules ['l-table']={
}
local type,next,tostring,tonumber,select=type,next,tostring,tonumber,select
local table,string=table,string
-local concat,sort,insert,remove=table.concat,table.sort,table.insert,table.remove
+local concat,sort=table.concat,table.sort
local format,lower,dump=string.format,string.lower,string.dump
local getmetatable,setmetatable=getmetatable,setmetatable
local lpegmatch,patterns=lpeg.match,lpeg.patterns
@@ -1055,7 +1054,8 @@ function table.getn(t)
return t and #t
end
function table.strip(tab)
- local lst,l={},0
+ local lst={}
+ local l=0
for i=1,#tab do
local s=lpegmatch(stripper,tab[i]) or ""
if s=="" then
@@ -1068,7 +1068,8 @@ function table.strip(tab)
end
function table.keys(t)
if t then
- local keys,k={},0
+ local keys={}
+ local k=0
for key in next,t do
k=k+1
keys[k]=key
@@ -1099,27 +1100,30 @@ local function compare(a,b)
end
local function sortedkeys(tab)
if tab then
- local srt,category,s={},0,0
+ local srt={}
+ local category=0
+ local s=0
for key in next,tab do
s=s+1
srt[s]=key
- if category==3 then
- elseif category==1 then
- if type(key)~="string" then
- category=3
- end
- elseif category==2 then
- if type(key)~="number" then
- category=3
- end
- else
+ if category~=3 then
local tkey=type(key)
- if tkey=="string" then
- category=1
- elseif tkey=="number" then
- category=2
+ if category==1 then
+ if tkey~="string" then
+ category=3
+ end
+ elseif category==2 then
+ if tkey~="number" then
+ category=3
+ end
else
- category=3
+ if tkey=="string" then
+ category=1
+ elseif tkey=="number" then
+ category=2
+ else
+ category=3
+ end
end
end
end
@@ -1136,7 +1140,8 @@ local function sortedkeys(tab)
end
local function sortedhashonly(tab)
if tab then
- local srt,s={},0
+ local srt={}
+ local s=0
for key in next,tab do
if type(key)=="string" then
s=s+1
@@ -1153,7 +1158,8 @@ local function sortedhashonly(tab)
end
local function sortedindexonly(tab)
if tab then
- local srt,s={},0
+ local srt={}
+ local s=0
for key in next,tab do
if type(key)=="number" then
s=s+1
@@ -1170,7 +1176,8 @@ local function sortedindexonly(tab)
end
local function sortedhashkeys(tab,cmp)
if tab then
- local srt,s={},0
+ local srt={}
+ local s=0
for key in next,tab do
if key then
s=s+1
@@ -1246,7 +1253,9 @@ function table.prepend(t,list)
return t
end
function table.merge(t,...)
- t=t or {}
+ if not t then
+ t={}
+ end
for i=1,select("#",...) do
for k,v in next,(select(i,...)) do
t[k]=v
@@ -1275,7 +1284,8 @@ function table.imerge(t,...)
return t
end
function table.imerged(...)
- local tmp,ntmp={},0
+ local tmp={}
+ local ntmp=0
for i=1,select("#",...) do
local nst=select(i,...)
for j=1,#nst do
@@ -1307,7 +1317,9 @@ local function fastcopy(old,metatabletoo)
end
end
local function copy(t,tables)
- tables=tables or {}
+ if not tables then
+ tables={}
+ end
local tcopy={}
if not tables[t] then
tables[t]=tcopy
@@ -1354,7 +1366,8 @@ function table.tohash(t,value)
return h
end
function table.fromhash(t)
- local hsh,h={},0
+ local hsh={}
+ local h=0
for k,v in next,t do
if v then
h=h+1
@@ -1455,7 +1468,8 @@ local function do_serialize(root,name,depth,level,indexed)
end
end
if root and next(root)~=nil then
- local first,last=nil,0
+ local first=nil
+ local last=0
if compact then
last=#root
for k=1,last do
@@ -1714,7 +1728,8 @@ local function serialize(_handle,root,name,specification)
handle("}")
end
function table.serialize(root,name,specification)
- local t,n={},0
+ local t={}
+ local n=0
local function flush(s)
n=n+1
t[n]=s
@@ -1728,13 +1743,15 @@ function table.tofile(filename,root,name,specification)
local f=io.open(filename,'w')
if f then
if maxtab>1 then
- local t,n={},0
+ local t={}
+ local n=0
local function flush(s)
n=n+1
t[n]=s
if n>maxtab then
f:write(concat(t,"\n"),"\n")
- t,n={},0
+ t={}
+ n=0
end
end
serialize(flush,root,name,specification)
@@ -1836,8 +1853,12 @@ local function are_equal(a,b,n,m)
if a==b then
return true
elseif a and b and #a==#b then
- n=n or 1
- m=m or #a
+ if not n then
+ n=1
+ end
+ if not m then
+ m=#a
+ end
for i=n,m do
local ai,bi=a[i],b[i]
if ai==bi then
@@ -1937,7 +1958,8 @@ function table.mirrored(t)
end
function table.reversed(t)
if t then
- local tt,tn={},#t
+ local tt={}
+ local tn=#t
if tn>0 then
local ttn=0
for i=tn,1,-1 do
@@ -2050,7 +2072,9 @@ function table.sorted(t,...)
end
function table.values(t,s)
if t then
- local values,keys,v={},{},0
+ local values={}
+ local keys={}
+ local v=0
for key,value in next,t do
if not keys[value] then
v=v+1
@@ -2652,40 +2676,45 @@ local reslasher=lpeg.replacer(P("\\"),"/")
function file.reslash(str)
return str and lpegmatch(reslasher,str)
end
-function file.is_writable(name)
- if not name then
- elseif lfs.isdir(name) then
- name=name.."/m_t_x_t_e_s_t.tmp"
- local f=io.open(name,"wb")
- if f then
- f:close()
- os.remove(name)
- return true
- end
- elseif lfs.isfile(name) then
- local f=io.open(name,"ab")
- if f then
- f:close()
- return true
- end
- else
- local f=io.open(name,"ab")
- if f then
- f:close()
- os.remove(name)
- return true
+if lfs.isreadablefile and lfs.iswritablefile then
+ file.is_readable=lfs.isreadablefile
+ file.is_writable=lfs.iswritablefile
+else
+ function file.is_writable(name)
+ if not name then
+ elseif lfs.isdir(name) then
+ name=name.."/m_t_x_t_e_s_t.tmp"
+ local f=io.open(name,"wb")
+ if f then
+ f:close()
+ os.remove(name)
+ return true
+ end
+ elseif lfs.isfile(name) then
+ local f=io.open(name,"ab")
+ if f then
+ f:close()
+ return true
+ end
+ else
+ local f=io.open(name,"ab")
+ if f then
+ f:close()
+ os.remove(name)
+ return true
+ end
end
- end
- return false
-end
-local readable=P("r")*Cc(true)
-function file.is_readable(name)
- if name then
- local a=attributes(name)
- return a and lpegmatch(readable,a.permissions) or false
- else
return false
end
+ local readable=P("r")*Cc(true)
+ function file.is_readable(name)
+ if name then
+ local a=attributes(name)
+ return a and lpegmatch(readable,a.permissions) or false
+ else
+ return false
+ end
+ end
end
file.isreadable=file.is_readable
file.iswritable=file.is_writable
@@ -3045,7 +3074,6 @@ local format,gsub,rep,sub,find=string.format,string.gsub,string.rep,string.sub,s
local load,dump=load,string.dump
local tonumber,type,tostring,next,setmetatable=tonumber,type,tostring,next,setmetatable
local unpack,concat=table.unpack,table.concat
-local unpack,concat=table.unpack,table.concat
local P,V,C,S,R,Ct,Cs,Cp,Carg,Cc=lpeg.P,lpeg.V,lpeg.C,lpeg.S,lpeg.R,lpeg.Ct,lpeg.Cs,lpeg.Cp,lpeg.Carg,lpeg.Cc
local patterns,lpegmatch=lpeg.patterns,lpeg.match
local utfchar,utfbyte,utflen=utf.char,utf.byte,utf.len
@@ -3384,8 +3412,8 @@ local environment={
formattednumber=number.formatted,
sparseexponent=number.sparseexponent,
formattedfloat=number.formattedfloat,
- stripzero=lpeg.patterns.stripzero,
- stripzeros=lpeg.patterns.stripzeros,
+ stripzero=patterns.stripzero,
+ stripzeros=patterns.stripzeros,
FORMAT=string.f9,
}
local arguments={ "a1" }
@@ -3472,7 +3500,7 @@ local format_F=function(f)
end
local format_k=function(b,a)
n=n+1
- return format("formattedfloat(a%s,%i,%i)",n,b or 0,a or 0)
+ return format("formattedfloat(a%s,%s,%s)",n,b or 0,a or 0)
end
local format_g=function(f)
n=n+1
@@ -3828,9 +3856,9 @@ patterns.xmlescape=Cs((P("<")/"&lt;"+P(">")/"&gt;"+P("&")/"&amp;"+P('"')/"&quot;
patterns.texescape=Cs((C(S("#$%\\{}"))/"\\%1"+anything)^0)
patterns.luaescape=Cs(((1-S('"\n'))^1+P('"')/'\\"'+P('\n')/'\\n"')^0)
patterns.luaquoted=Cs(Cc('"')*((1-S('"\n'))^1+P('"')/'\\"'+P('\n')/'\\n"')^0*Cc('"'))
-add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],{ xmlescape=lpeg.patterns.xmlescape })
-add(formatters,"tex",[[lpegmatch(texescape,%s)]],{ texescape=lpeg.patterns.texescape })
-add(formatters,"lua",[[lpegmatch(luaescape,%s)]],{ luaescape=lpeg.patterns.luaescape })
+add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],{ xmlescape=patterns.xmlescape })
+add(formatters,"tex",[[lpegmatch(texescape,%s)]],{ texescape=patterns.texescape })
+add(formatters,"lua",[[lpegmatch(luaescape,%s)]],{ luaescape=patterns.luaescape })
local dquote=patterns.dquote
local equote=patterns.escaped+dquote/'\\"'+1
local cquote=Cc('"')
@@ -3862,6 +3890,27 @@ local f_16_16=formatters["%0.5N"]
function number.to16dot16(n)
return f_16_16(n/65536.0)
end
+if not string.explode then
+ local tsplitat=lpeg.tsplitat
+ local p_utf=patterns.utf8character
+ local p_check=C(p_utf)*(P("+")*Cc(true))^0
+ local p_split=Ct(C(p_utf)^0)
+ local p_space=Ct((C(1-P(" ")^1)+P(" ")^1)^0)
+ function string.explode(str,symbol)
+ if symbol=="" then
+ return lpegmatch(p_split,str)
+ elseif symbol then
+ local a,b=lpegmatch(p_check,symbol)
+ if b then
+ return lpegmatch(tsplitat(P(a)^1),str)
+ else
+ return lpegmatch(tsplitat(a),str)
+ end
+ else
+ return lpegmatch(p_space,str)
+ end
+ end
+end
end -- closure
@@ -4074,6 +4123,32 @@ if bit32 then
local b=char(n%256)
f:write(b,a)
end
+ function files.writecardinal4(f,n)
+ local a=char(n%256)
+ n=rshift(n,8)
+ local b=char(n%256)
+ n=rshift(n,8)
+ local c=char(n%256)
+ n=rshift(n,8)
+ local d=char(n%256)
+ f:write(d,c,b,a)
+ end
+ function files.writecardinal2le(f,n)
+ local a=char(n%256)
+ n=rshift(n,8)
+ local b=char(n%256)
+ f:write(a,b)
+ end
+ function files.writecardinal4le(f,n)
+ local a=char(n%256)
+ n=rshift(n,8)
+ local b=char(n%256)
+ n=rshift(n,8)
+ local c=char(n%256)
+ n=rshift(n,8)
+ local d=char(n%256)
+ f:write(a,b,c,d)
+ end
else
local floor=math.floor
function files.writecardinal2(f,n)
@@ -4082,16 +4157,32 @@ else
local b=char(n%256)
f:write(b,a)
end
-end
-function files.writecardinal4(f,n)
- local a=char(n%256)
- n=rshift(n,8)
- local b=char(n%256)
- n=rshift(n,8)
- local c=char(n%256)
- n=rshift(n,8)
- local d=char(n%256)
- f:write(d,c,b,a)
+ function files.writecardinal4(f,n)
+ local a=char(n%256)
+ n=floor(n/256)
+ local b=char(n%256)
+ n=floor(n/256)
+ local c=char(n%256)
+ n=floor(n/256)
+ local d=char(n%256)
+ f:write(d,c,b,a)
+ end
+ function files.writecardinal2le(f,n)
+ local a=char(n%256)
+ n=floor(n/256)
+ local b=char(n%256)
+ f:write(a,b)
+ end
+ function files.writecardinal4le(f,n)
+ local a=char(n%256)
+ n=floor(n/256)
+ local b=char(n%256)
+ n=floor(n/256)
+ local c=char(n%256)
+ n=floor(n/256)
+ local d=char(n%256)
+ f:write(a,b,c,d)
+ end
end
function files.writestring(f,s)
f:write(char(byte(s,1,#s)))
@@ -4104,10 +4195,18 @@ if fio and fio.readcardinal1 then
files.readcardinal2=fio.readcardinal2
files.readcardinal3=fio.readcardinal3
files.readcardinal4=fio.readcardinal4
+ files.readcardinal1le=fio.readcardinal1le or files.readcardinal1le
+ files.readcardinal2le=fio.readcardinal2le or files.readcardinal2le
+ files.readcardinal3le=fio.readcardinal3le or files.readcardinal3le
+ files.readcardinal4le=fio.readcardinal4le or files.readcardinal4le
files.readinteger1=fio.readinteger1
files.readinteger2=fio.readinteger2
files.readinteger3=fio.readinteger3
files.readinteger4=fio.readinteger4
+ files.readinteger1le=fio.readinteger1le or files.readinteger1le
+ files.readinteger2le=fio.readinteger2le or files.readinteger2le
+ files.readinteger3le=fio.readinteger3le or files.readinteger3le
+ files.readinteger4le=fio.readinteger4le or files.readinteger4le
files.readfixed2=fio.readfixed2
files.readfixed4=fio.readfixed4
files.read2dot14=fio.read2dot14
@@ -4128,6 +4227,24 @@ if fio and fio.readcardinal1 then
skipposition(f,4*(n or 1))
end
end
+if fio and fio.writecardinal1 then
+ files.writecardinal1=fio.writecardinal1
+ files.writecardinal2=fio.writecardinal2
+ files.writecardinal3=fio.writecardinal3
+ files.writecardinal4=fio.writecardinal4
+ files.writecardinal1le=fio.writecardinal1le
+ files.writecardinal2le=fio.writecardinal2le
+ files.writecardinal3le=fio.writecardinal3le
+ files.writecardinal4le=fio.writecardinal4le
+ files.writeinteger1=fio.writeinteger1 or fio.writecardinal1
+ files.writeinteger2=fio.writeinteger2 or fio.writecardinal2
+ files.writeinteger3=fio.writeinteger3 or fio.writecardinal3
+ files.writeinteger4=fio.writeinteger4 or fio.writecardinal4
+ files.writeinteger1le=files.writeinteger1le or fio.writecardinal1le
+ files.writeinteger2le=files.writeinteger2le or fio.writecardinal2le
+ files.writeinteger3le=files.writeinteger3le or fio.writecardinal3le
+ files.writeinteger4le=files.writeinteger4le or fio.writecardinal4le
+end
if fio and fio.readcardinaltable then
files.readcardinaltable=fio.readcardinaltable
files.readintegertable=fio.readintegertable
@@ -4712,67 +4829,8 @@ end
nodes.nodecodes=nodecodes
nodes.glyphcodes=glyphcodes
nodes.disccodes=disccodes
-local flush_node=node.flush_node
-local remove_node=node.remove
-local traverse_id=node.traverse_id
nodes.handlers.protectglyphs=node.protect_glyphs
-nodes.handlers.unprotectglyphs=node.unprotect_glyphs
-function nodes.remove(head,current,free_too)
- local t=current
- head,current=remove_node(head,current)
- if t then
- if free_too then
- flush_node(t)
- t=nil
- else
- t.next,t.prev=nil,nil
- end
- end
- return head,current,t
-end
-function nodes.delete(head,current)
- return nodes.remove(head,current,true)
-end
-local getfield=node.getfield
-local setfield=node.setfield
-nodes.getfield=getfield
-nodes.setfield=setfield
-nodes.getattr=getfield
-nodes.setattr=setfield
-nodes.tostring=node.tostring or tostring
-nodes.copy=node.copy
-nodes.copy_node=node.copy
-nodes.copy_list=node.copy_list
-nodes.delete=node.delete
-nodes.dimensions=node.dimensions
-nodes.end_of_math=node.end_of_math
-nodes.flush_list=node.flush_list
-nodes.flush_node=node.flush_node
-nodes.flush=node.flush_node
-nodes.free=node.free
-nodes.insert_after=node.insert_after
-nodes.insert_before=node.insert_before
-nodes.hpack=node.hpack
-nodes.new=node.new
-nodes.tail=node.tail
-nodes.traverse=node.traverse
-nodes.traverse_id=node.traverse_id
-nodes.slide=node.slide
-nodes.vpack=node.vpack
-nodes.first_glyph=node.first_glyph
-nodes.has_glyph=node.has_glyph or node.first_glyph
-nodes.current_attr=node.current_attr
-nodes.has_field=node.has_field
-nodes.last_node=node.last_node
-nodes.usedlist=node.usedlist
-nodes.protrusion_skippable=node.protrusion_skippable
-nodes.write=node.write
-nodes.has_attribute=node.has_attribute
-nodes.set_attribute=node.set_attribute
-nodes.unset_attribute=node.unset_attribute
-nodes.protect_glyphs=node.protect_glyphs
-nodes.unprotect_glyphs=node.unprotect_glyphs
-nodes.mlist_to_hlist=node.mlist_to_hlist
+nodes.handlers.unprotectglyphs=node.unprotect_glyphs
local direct=node.direct
local nuts={}
nodes.nuts=nuts
@@ -8637,7 +8695,6 @@ function constructors.scale(tfmdata,specification)
local hasitalics=properties.hasitalics
local autoitalicamount=properties.autoitalicamount
local stackmath=not properties.nostackmath
- local nonames=properties.noglyphnames
local haskerns=properties.haskerns or properties.mode=="base"
local hasligatures=properties.hasligatures or properties.mode=="base"
local realdimensions=properties.realdimensions
@@ -8744,6 +8801,7 @@ function constructors.scale(tfmdata,specification)
local width=description.width
local height=description.height
local depth=description.depth
+ local isunicode=description.unicode
if realdimensions then
if not height or height==0 then
local bb=description.boundingbox
@@ -8768,16 +8826,16 @@ function constructors.scale(tfmdata,specification)
if height then height=vdelta*height else height=scaledheight end
if depth and depth~=0 then
depth=delta*depth
- if nonames then
+ if isunicode then
chr={
index=index,
height=height,
depth=depth,
width=width,
+ unicode=isunicode,
}
else
chr={
- name=description.name,
index=index,
height=height,
depth=depth,
@@ -8785,33 +8843,23 @@ function constructors.scale(tfmdata,specification)
}
end
else
- if nonames then
+ if isunicode then
chr={
index=index,
height=height,
width=width,
+ unicode=isunicode,
}
else
chr={
- name=description.name,
index=index,
height=height,
width=width,
}
end
end
- local isunicode=description.unicode
if addtounicode then
- if isunicode then
- chr.unicode=isunicode
- chr.tounicode=tounicode(isunicode)
- else
- chr.tounicode=unknowncode
- end
- else
- if isunicode then
- chr.unicode=isunicode
- end
+ chr.tounicode=isunicode and tounicode(isunicode) or unknowncode
end
if hasquality then
local ve=character.expansion_factor
@@ -8881,7 +8929,10 @@ function constructors.scale(tfmdata,specification)
if stackmath then
local mk=character.mathkerns
if mk then
- local tr,tl,br,bl=mk.topright,mk.topleft,mk.bottomright,mk.bottomleft
+ local tr=mk.topright
+ local tl=mk.topleft
+ local br=mk.bottomright
+ local bl=mk.bottomleft
chr.mathkern={
top_right=tr and mathkerns(tr,vdelta) or nil,
top_left=tl and mathkerns(tl,vdelta) or nil,
@@ -9167,7 +9218,9 @@ hashmethods.normal=function(list)
end
end
function constructors.hashinstance(specification,force)
- local hash,size,fallbacks=specification.hash,specification.size,specification.fallbacks
+ local hash=specification.hash
+ local size=specification.size
+ local fallbacks=specification.fallbacks
if force or not hash then
hash=constructors.hashfeatures(specification)
specification.hash=hash
@@ -9534,7 +9587,8 @@ function constructors.initializefeatures(what,tfmdata,features,trace,report)
end
end
function constructors.collectprocessors(what,tfmdata,features,trace,report)
- local processes,nofprocesses={},0
+ local processes={}
+ local nofprocesses=0
if features and next(features) then
local properties=tfmdata.properties
local whathandler=handlers[what]
@@ -10071,7 +10125,8 @@ function mappings.addtounicode(data,filename,checklookups,forceligatures)
glyph.unicode=unicode
end
else
- local t,n={},0
+ local t={}
+ local n=0
for l=1,nsplit do
local base=split[l]
local u=unicodes[base] or unicodevector[base] or contextvector[name]
@@ -10410,7 +10465,6 @@ local P,R,S,C,Cs,Cc,Ct,Carg,Cmt=lpeg.P,lpeg.R,lpeg.S,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg
local lpegmatch=lpeg.match
local rshift=bit32.rshift
local setmetatableindex=table.setmetatableindex
-local formatters=string.formatters
local sortedkeys=table.sortedkeys
local sortedhash=table.sortedhash
local stripstring=string.nospaces
@@ -14945,7 +14999,8 @@ end
end
end
local function setbias(globals,locals)
- local g,l=#globals,#locals
+ local g=#globals
+ local l=#locals
return
((g<1240 and 107) or (g<33900 and 1131) or 32768)+1,
((l<1240 and 107) or (l<33900 and 1131) or 32768)+1
@@ -15681,7 +15736,8 @@ local function contours2outlines_normal(glyphs,shapes)
local nofsegments=0
glyph.segments=segments
if nofcontours>0 then
- local px,py=0,0
+ local px=0
+ local py=0
local first=1
for i=1,nofcontours do
local last=contours[i]
@@ -15708,15 +15764,20 @@ local function contours2outlines_normal(glyphs,shapes)
end
control_pt=first_pt
end
- local x,y=first_pt[1],first_pt[2]
+ local x=first_pt[1]
+ local y=first_pt[2]
if not done then
- xmin,ymin,xmax,ymax=x,y,x,y
+ xmin=x
+ ymin=y
+ xmax=x
+ ymax=y
done=true
end
nofsegments=nofsegments+1
segments[nofsegments]={ x,y,"m" }
if not quadratic then
- px,py=x,y
+ px=x
+ py=y
end
local previous_pt=first_pt
for i=first,last do
@@ -15735,8 +15796,10 @@ local function contours2outlines_normal(glyphs,shapes)
control_pt=current_pt
end
elseif current_on then
- local x1,y1=control_pt[1],control_pt[2]
- local x2,y2=current_pt[1],current_pt[2]
+ local x1=control_pt[1]
+ local y1=control_pt[2]
+ local x2=current_pt[1]
+ local y2=current_pt[2]
nofsegments=nofsegments+1
if quadratic then
segments[nofsegments]={ x1,y1,x2,y2,"q" }
@@ -15746,8 +15809,10 @@ local function contours2outlines_normal(glyphs,shapes)
end
control_pt=false
else
- local x2,y2=(previous_pt[1]+current_pt[1])/2,(previous_pt[2]+current_pt[2])/2
- local x1,y1=control_pt[1],control_pt[2]
+ local x2=(previous_pt[1]+current_pt[1])/2
+ local y2=(previous_pt[2]+current_pt[2])/2
+ local x1=control_pt[1]
+ local y1=control_pt[2]
nofsegments=nofsegments+1
if quadratic then
segments[nofsegments]={ x1,y1,x2,y2,"q" }
@@ -15762,14 +15827,17 @@ local function contours2outlines_normal(glyphs,shapes)
if first_pt==last_pt then
else
nofsegments=nofsegments+1
- local x2,y2=first_pt[1],first_pt[2]
+ local x2=first_pt[1]
+ local y2=first_pt[2]
if not control_pt then
segments[nofsegments]={ x2,y2,"l" }
elseif quadratic then
- local x1,y1=control_pt[1],control_pt[2]
+ local x1=control_pt[1]
+ local y1=control_pt[2]
segments[nofsegments]={ x1,y1,x2,y2,"q" }
else
- local x1,y1=control_pt[1],control_pt[2]
+ local x1=control_pt[1]
+ local y1=control_pt[2]
x1,y1,x2,y2,px,py=curveto(x1,y1,px,py,x2,y2)
segments[nofsegments]={ x1,y1,x2,y2,px,py,"c" }
end
@@ -15828,7 +15896,8 @@ local function contours2outlines_shaped(glyphs,shapes,keepcurve)
end
control_pt=first_pt
end
- local x,y=first_pt[1],first_pt[2]
+ local x=first_pt[1]
+ local y=first_pt[2]
if not done then
xmin,ymin,xmax,ymax=x,y,x,y
done=true
@@ -15841,7 +15910,8 @@ local function contours2outlines_shaped(glyphs,shapes,keepcurve)
segments[nofsegments]={ x,y,"m" }
end
if not quadratic then
- px,py=x,y
+ px=x
+ py=y
end
local previous_pt=first_pt
for i=first,last do
@@ -15850,7 +15920,8 @@ local function contours2outlines_shaped(glyphs,shapes,keepcurve)
local previous_on=previous_pt[3]
if previous_on then
if current_on then
- local x,y=current_pt[1],current_pt[2]
+ local x=current_pt[1]
+ local y=current_pt[2]
if x<xmin then xmin=x elseif x>xmax then xmax=x end
if y<ymin then ymin=y elseif y>ymax then ymax=y end
if keepcurve then
@@ -15858,14 +15929,17 @@ local function contours2outlines_shaped(glyphs,shapes,keepcurve)
segments[nofsegments]={ x,y,"l" }
end
if not quadratic then
- px,py=x,y
+ px=x
+ py=y
end
else
control_pt=current_pt
end
elseif current_on then
- local x1,y1=control_pt[1],control_pt[2]
- local x2,y2=current_pt[1],current_pt[2]
+ local x1=control_pt[1]
+ local y1=control_pt[2]
+ local x2=current_pt[1]
+ local y2=current_pt[2]
if quadratic then
if x1<xmin then xmin=x1 elseif x1>xmax then xmax=x1 end
if y1<ymin then ymin=y1 elseif y1>ymax then ymax=y1 end
@@ -15888,8 +15962,10 @@ local function contours2outlines_shaped(glyphs,shapes,keepcurve)
end
control_pt=false
else
- local x2,y2=(previous_pt[1]+current_pt[1])/2,(previous_pt[2]+current_pt[2])/2
- local x1,y1=control_pt[1],control_pt[2]
+ local x2=(previous_pt[1]+current_pt[1])/2
+ local y2=(previous_pt[2]+current_pt[2])/2
+ local x1=control_pt[1]
+ local y1=control_pt[2]
if quadratic then
if x1<xmin then xmin=x1 elseif x1>xmax then xmax=x1 end
if y1<ymin then ymin=y1 elseif y1>ymax then ymax=y1 end
@@ -15921,8 +15997,10 @@ local function contours2outlines_shaped(glyphs,shapes,keepcurve)
segments[nofsegments]={ first_pt[1],first_pt[2],"l" }
end
else
- local x1,y1=control_pt[1],control_pt[2]
- local x2,y2=first_pt[1],first_pt[2]
+ local x1=control_pt[1]
+ local y1=control_pt[2]
+ local x2=first_pt[1]
+ local y2=first_pt[2]
if x1<xmin then xmin=x1 elseif x1>xmax then xmax=x1 end
if y1<ymin then ymin=y1 elseif y1>ymax then ymax=y1 end
if quadratic then
@@ -19587,12 +19665,13 @@ function readers.avar(f,fontdata,specification)
local lastfrom=false
local lastto=false
for i=1,nofvalues do
- local f,t=read2dot14(f),read2dot14(f)
- if lastfrom and f<=lastfrom then
- elseif lastto and t>=lastto then
+ local from=read2dot14(f)
+ local to=read2dot14(f)
+ if lastfrom and from<=lastfrom then
+ elseif lastto and to>=lastto then
else
- values[#values+1]={ f,t }
- lastfrom,lastto=f,t
+ values[#values+1]={ from,to }
+ lastfrom,lastto=from,to
end
end
nofvalues=#values
@@ -21074,7 +21153,9 @@ function readers.pack(data)
end
return false
elseif nt>=threshold then
- local one,two,rest=0,0,0
+ local one=0
+ local two=0
+ local rest=0
if pass==1 then
for k,v in next,c do
if v==1 then
@@ -22822,7 +22903,6 @@ local function copytotfm(data,cache_id)
properties.space=spacer
properties.encodingbytes=2
properties.format=data.format or formats.otf
- properties.noglyphnames=true
properties.filename=filename
properties.fontname=fontname
properties.fullname=fullname
@@ -23176,7 +23256,9 @@ local function gref(descriptions,n)
return f_unicode(n)
end
elseif n then
- local num,nam,j={},{},0
+ local num={}
+ local nam={}
+ local j=0
for i=1,#n do
local ni=n[i]
if tonumber(ni) then
@@ -23381,12 +23463,15 @@ local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplis
local done=trace_baseinit and trace_ligatures and {}
for i=1,nofligatures do
local ligature=ligatures[i]
- local unicode,tree=ligature[1],ligature[2]
+ local unicode=ligature[1]
+ local tree=ligature[2]
make_1(present,tree,"ctx_"..unicode)
end
for i=1,nofligatures do
local ligature=ligatures[i]
- local unicode,tree,lookupname=ligature[1],ligature[2],ligature[3]
+ local unicode=ligature[1]
+ local tree=ligature[2]
+ local lookupname=ligature[3]
make_2(present,tfmdata,characters,tree,"ctx_"..unicode,unicode,unicode,done,sequence)
end
end
@@ -23952,7 +24037,8 @@ function injections.setmove(current,factor,rlmode,x,injection)
end
end
function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk,checkmark)
- local dx,dy=factor*(ba[1]-ma[1]),factor*(ba[2]-ma[2])
+ local dx=factor*(ba[1]-ma[1])
+ local dy=factor*(ba[2]-ma[2])
nofregisteredmarks=nofregisteredmarks+1
if rlmode>=0 then
dx=tfmbase.width-dx
@@ -25278,9 +25364,9 @@ if not classifiers then
characters.classifiers=classifiers
end
function methods.arab(head,font,attr)
- local first,last=nil,nil
- local c_first,c_last=nil,nil
- local current,done=head,false
+ local first,last,c_first,c_last
+ local current=head
+ local done=false
current=tonut(current)
while current do
local char,id=ischar(current,font)
@@ -26021,8 +26107,8 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature,rlmode,skip
local prev=getprev(start)
if stop then
setnext(stop)
- local tail=getprev(stop)
local copy=copy_node_list(start)
+ local tail=stop
local liat=find_node_tail(copy)
if pre then
setlink(liat,pre)
@@ -26113,7 +26199,8 @@ function handlers.gpos_pair(head,start,dataset,sequence,kerns,rlmode,skiphash,st
end
local format=step.format
if format=="pair" then
- local a,b=krn[1],krn[2]
+ local a=krn[1]
+ local b=krn[2]
if a==true then
elseif a then
local x,y,w,h=setposition(1,start,factor,rlmode,a,injection)
@@ -26631,7 +26718,8 @@ function chainprocs.gpos_pair(head,start,stop,dataset,sequence,currentlookup,rlm
end
local format=currentlookup.format
if format=="pair" then
- local a,b=krn[1],krn[2]
+ local a=krn[1]
+ local b=krn[2]
if a==true then
elseif a then
local x,y,w,h=setposition(1,start,factor,rlmode,a,"injections")
@@ -30034,7 +30122,7 @@ function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start)
end
function handlers.devanagari_remove_joiners(head,start,kind,lookupname,replacement)
local stop=getnext(start)
- local font=getfont(start)
+ local font=getfont(start)
local last=start
while stop do
local char=ischar(stop,font)
@@ -31668,7 +31756,8 @@ local function addfeature(data,feature,specifications)
if not nocheck and not description then
skip=skip+1
elseif type(replacement)=="table" then
- local r,n={},0
+ local r={}
+ local n=0
for i=1,#replacement do
local u=tounicode(replacement[i])
if nocheck or descriptions[u] then
@@ -32601,13 +32690,15 @@ function afm.load(filename)
local name=file.removesuffix(file.basename(filename))
local data=containers.read(afm.cache,name)
local attr=lfs.attributes(filename)
- local size,time=attr and attr.size or 0,attr and attr.modification or 0
+ local size=attr and attr.size or 0
+ local time=attr and attr.modification or 0
local pfbfile=file.replacesuffix(name,"pfb")
local pfbname=resolvers.findfile(pfbfile,"pfb") or ""
if pfbname=="" then
pfbname=resolvers.findfile(file.basename(pfbfile),"pfb") or ""
end
- local pfbsize,pfbtime=0,0
+ local pfbsize=0
+ local pfbtime=0
if pfbname~="" then
local attr=lfs.attributes(pfbname)
pfbsize=attr.size or 0
@@ -32816,7 +32907,8 @@ local addthem=function(rawdata,ligatures)
local one=descriptions[unicodes[ligname]]
if one then
for _,pair in next,ligdata do
- local two,three=unicodes[pair[1]],unicodes[pair[2]]
+ local two=unicodes[pair[1]]
+ local three=unicodes[pair[2]]
if two and three then
local ol=one.ligatures
if ol then
@@ -32916,7 +33008,8 @@ local function adddimensions(data)
for unicode,description in next,data.descriptions do
local bb=description.boundingbox
if bb then
- local ht,dp=bb[4],-bb[2]
+ local ht=bb[4]
+ local dp=-bb[2]
if ht==0 or ht<0 then
else
description.height=ht
@@ -33182,7 +33275,7 @@ local function check_afm(specification,fullname)
if foundname=="" then
foundname=fonts.names.getfilename(fullname,"afm") or ""
end
- if foundname=="" and afm.autoprefixed then
+ if fullname and foundname=="" and afm.autoprefixed then
local encoding,shortname=match(fullname,"^(.-)%-(.*)$")
if encoding and shortname and fonts.encodings.known[encoding] then
shortname=findbinfile(shortname,'afm') or ""
diff --git a/tex/generic/context/luatex/luatex-fonts.lua b/tex/generic/context/luatex/luatex-fonts.lua
index 69908dfcc..06fb682f3 100644
--- a/tex/generic/context/luatex/luatex-fonts.lua
+++ b/tex/generic/context/luatex/luatex-fonts.lua
@@ -209,8 +209,8 @@ if non_generic_context.luatex_fonts.skip_loading ~= true then
-- A few slightly higher level support modules:
- loadmodule("util-str.lua")
- loadmodule("util-fil.lua")
+ loadmodule("util-str.lua") -- future versions can ship without this one
+ loadmodule("util-fil.lua") -- future versions can ship without this one
-- The following modules contain code that is either not used at all
-- outside context or will fail when enabled due to lack of other
diff --git a/tex/generic/context/luatex/luatex-plain.tex b/tex/generic/context/luatex/luatex-plain.tex
index 0a806c76f..f45608f7a 100644
--- a/tex/generic/context/luatex/luatex-plain.tex
+++ b/tex/generic/context/luatex/luatex-plain.tex
@@ -52,4 +52,6 @@
\edef\fmtversion{\fmtversion+luatex}
+\automatichyphenmode=1
+
\dump