summaryrefslogtreecommitdiff
path: root/tex
diff options
context:
space:
mode:
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-cs.mkii1
-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-fr.mkii1
-rw-r--r--tex/context/base/mkii/mult-it.mkii1
-rw-r--r--tex/context/base/mkii/mult-nl.mkii1
-rw-r--r--tex/context/base/mkii/mult-pe.mkii1
-rw-r--r--tex/context/base/mkii/mult-ro.mkii1
-rw-r--r--tex/context/base/mkiv/anch-bck.mkvi13
-rw-r--r--tex/context/base/mkiv/anch-pgr.lua10
-rw-r--r--tex/context/base/mkiv/anch-pos.lua11
-rw-r--r--tex/context/base/mkiv/attr-col.lua22
-rw-r--r--tex/context/base/mkiv/attr-eff.lua4
-rw-r--r--tex/context/base/mkiv/attr-ini.mkiv23
-rw-r--r--tex/context/base/mkiv/attr-lay.lua7
-rw-r--r--tex/context/base/mkiv/attr-neg.lua4
-rw-r--r--tex/context/base/mkiv/back-exp.lua52
-rw-r--r--tex/context/base/mkiv/back-ini.lua12
-rw-r--r--tex/context/base/mkiv/back-pdf.lua136
-rw-r--r--tex/context/base/mkiv/back-pdf.mkiv59
-rw-r--r--tex/context/base/mkiv/bibl-tra.lua33
-rw-r--r--tex/context/base/mkiv/buff-ini.lua19
-rw-r--r--tex/context/base/mkiv/cldf-ini.lua2
-rw-r--r--tex/context/base/mkiv/colo-imp-solarized.mkiv38
-rw-r--r--tex/context/base/mkiv/cont-new.mkiv2
-rw-r--r--tex/context/base/mkiv/cont-run.lua5
-rw-r--r--tex/context/base/mkiv/context.mkiv2
-rw-r--r--tex/context/base/mkiv/core-con.lua24
-rw-r--r--tex/context/base/mkiv/core-con.mkiv19
-rw-r--r--tex/context/base/mkiv/core-ctx.lua5
-rw-r--r--tex/context/base/mkiv/core-uti.lua2
-rw-r--r--tex/context/base/mkiv/data-crl.lua36
-rw-r--r--tex/context/base/mkiv/data-sch.lua30
-rw-r--r--tex/context/base/mkiv/font-col.lua14
-rw-r--r--tex/context/base/mkiv/font-ctx.lua14
-rw-r--r--tex/context/base/mkiv/font-dsp.lua7
-rw-r--r--tex/context/base/mkiv/font-hsh.lua15
-rw-r--r--tex/context/base/mkiv/font-inj.lua2
-rw-r--r--tex/context/base/mkiv/font-map.lua26
-rw-r--r--tex/context/base/mkiv/font-mps.lua36
-rw-r--r--tex/context/base/mkiv/font-nod.lua12
-rw-r--r--tex/context/base/mkiv/font-ocl.lua123
-rw-r--r--tex/context/base/mkiv/font-osd.lua30
-rw-r--r--tex/context/base/mkiv/font-ota.lua1
-rw-r--r--tex/context/base/mkiv/font-otf.lua1
-rw-r--r--tex/context/base/mkiv/font-otj.lua606
-rw-r--r--tex/context/base/mkiv/font-otl.lua57
-rw-r--r--tex/context/base/mkiv/font-ots.lua1375
-rw-r--r--tex/context/base/mkiv/font-pre.mkiv11
-rw-r--r--tex/context/base/mkiv/font-sel.lua9
-rw-r--r--tex/context/base/mkiv/font-set.mkvi2
-rw-r--r--tex/context/base/mkiv/font-sol.lua9
-rw-r--r--tex/context/base/mkiv/font-web.lua28
-rw-r--r--tex/context/base/mkiv/grph-con.lua272
-rw-r--r--tex/context/base/mkiv/grph-fil.lua15
-rw-r--r--tex/context/base/mkiv/grph-inc.lua9
-rw-r--r--tex/context/base/mkiv/grph-inc.mkiv4
-rw-r--r--tex/context/base/mkiv/grph-rul.lua1
-rw-r--r--tex/context/base/mkiv/l-lpeg.lua99
-rw-r--r--tex/context/base/mkiv/l-lua.lua84
-rw-r--r--tex/context/base/mkiv/l-os.lua44
-rw-r--r--tex/context/base/mkiv/l-sandbox.lua105
-rw-r--r--tex/context/base/mkiv/l-unicode.lua32
-rw-r--r--tex/context/base/mkiv/lang-dis.lua82
-rw-r--r--tex/context/base/mkiv/lang-hyp.lua39
-rw-r--r--tex/context/base/mkiv/lang-rep.lua23
-rw-r--r--tex/context/base/mkiv/lang-wrd.lua7
-rw-r--r--tex/context/base/mkiv/lpdf-ano.lua1
-rw-r--r--tex/context/base/mkiv/lpdf-mis.lua4
-rw-r--r--tex/context/base/mkiv/lpdf-res.lua6
-rw-r--r--tex/context/base/mkiv/lpdf-tag.lua8
-rw-r--r--tex/context/base/mkiv/luat-cbk.lua9
-rw-r--r--tex/context/base/mkiv/luat-cod.lua26
-rw-r--r--tex/context/base/mkiv/luat-exe.lua132
-rw-r--r--tex/context/base/mkiv/luat-fmt.lua49
-rw-r--r--tex/context/base/mkiv/luat-ini.lua10
-rw-r--r--tex/context/base/mkiv/luat-iop.lua25
-rw-r--r--tex/context/base/mkiv/lxml-ini.lua2
-rw-r--r--tex/context/base/mkiv/lxml-ini.mkiv2
-rw-r--r--tex/context/base/mkiv/lxml-lpt.lua56
-rw-r--r--tex/context/base/mkiv/lxml-tex.lua6
-rw-r--r--tex/context/base/mkiv/math-dir.lua4
-rw-r--r--tex/context/base/mkiv/math-ini.lua32
-rw-r--r--tex/context/base/mkiv/math-ini.mkiv30
-rw-r--r--tex/context/base/mkiv/math-noa.lua240
-rw-r--r--tex/context/base/mkiv/math-tag.lua12
-rw-r--r--tex/context/base/mkiv/meta-imp-txt.mkiv3
-rw-r--r--tex/context/base/mkiv/meta-tex.lua2
-rw-r--r--tex/context/base/mkiv/mlib-lua.lua94
-rw-r--r--tex/context/base/mkiv/mlib-pps.lua53
-rw-r--r--tex/context/base/mkiv/mult-def.lua3
-rw-r--r--tex/context/base/mkiv/mult-low.lua1
-rw-r--r--tex/context/base/mkiv/mult-prm.lua2
-rw-r--r--tex/context/base/mkiv/mult-sys.mkiv3
-rw-r--r--tex/context/base/mkiv/node-acc.lua114
-rw-r--r--tex/context/base/mkiv/node-aux.lua192
-rw-r--r--tex/context/base/mkiv/node-bck.lua23
-rw-r--r--tex/context/base/mkiv/node-fin.lua130
-rw-r--r--tex/context/base/mkiv/node-fnt.lua188
-rw-r--r--tex/context/base/mkiv/node-ltp.lua1334
-rw-r--r--tex/context/base/mkiv/node-met.lua171
-rw-r--r--tex/context/base/mkiv/node-mig.lua9
-rw-r--r--tex/context/base/mkiv/node-nut.lua244
-rw-r--r--tex/context/base/mkiv/node-ppt.lua6
-rw-r--r--tex/context/base/mkiv/node-pro.lua236
-rw-r--r--tex/context/base/mkiv/node-ref.lua91
-rw-r--r--tex/context/base/mkiv/node-res.lua146
-rw-r--r--tex/context/base/mkiv/node-rul.lua55
-rw-r--r--tex/context/base/mkiv/node-ser.lua1
-rw-r--r--tex/context/base/mkiv/node-tra.lua27
-rw-r--r--tex/context/base/mkiv/node-tsk.lua64
-rw-r--r--tex/context/base/mkiv/node-tst.lua16
-rw-r--r--tex/context/base/mkiv/node-typ.lua7
-rw-r--r--tex/context/base/mkiv/pack-rul.lua36
-rw-r--r--tex/context/base/mkiv/page-cst.lua32
-rw-r--r--tex/context/base/mkiv/page-ins.mkiv4
-rw-r--r--tex/context/base/mkiv/page-lin.lua26
-rw-r--r--tex/context/base/mkiv/page-mix.lua56
-rw-r--r--tex/context/base/mkiv/page-str.lua8
-rw-r--r--tex/context/base/mkiv/publ-sor.lua1
-rw-r--r--tex/context/base/mkiv/scrn-fld.mkvi1
-rw-r--r--tex/context/base/mkiv/scrp-cjk.lua3
-rw-r--r--tex/context/base/mkiv/spac-adj.lua16
-rw-r--r--tex/context/base/mkiv/spac-ali.lua19
-rw-r--r--tex/context/base/mkiv/spac-chr.lua16
-rw-r--r--tex/context/base/mkiv/spac-prf.lua100
-rw-r--r--tex/context/base/mkiv/spac-ver.lua342
-rw-r--r--tex/context/base/mkiv/status-files.pdfbin25642 -> 25624 bytes
-rw-r--r--tex/context/base/mkiv/status-lua.pdfbin369339 -> 372482 bytes
-rw-r--r--tex/context/base/mkiv/strc-con.mkvi6
-rw-r--r--tex/context/base/mkiv/strc-doc.lua15
-rw-r--r--tex/context/base/mkiv/strc-doc.mkiv4
-rw-r--r--tex/context/base/mkiv/strc-enu.mkvi2
-rw-r--r--tex/context/base/mkiv/strc-itm.mkvi2
-rw-r--r--tex/context/base/mkiv/strc-lst.mkvi10
-rw-r--r--tex/context/base/mkiv/strc-mar.lua5
-rw-r--r--tex/context/base/mkiv/strc-mat.mkiv4
-rw-r--r--tex/context/base/mkiv/strc-not.lua32
-rw-r--r--tex/context/base/mkiv/strc-not.mkvi6
-rw-r--r--tex/context/base/mkiv/strc-num.mkiv8
-rw-r--r--tex/context/base/mkiv/strc-ref.mkvi12
-rw-r--r--tex/context/base/mkiv/strc-reg.mkiv6
-rw-r--r--tex/context/base/mkiv/strc-ren.mkiv8
-rw-r--r--tex/context/base/mkiv/strc-sec.mkiv8
-rw-r--r--tex/context/base/mkiv/supp-box.lua71
-rw-r--r--tex/context/base/mkiv/supp-box.mkiv4
-rw-r--r--tex/context/base/mkiv/syst-aux.mkiv2
-rw-r--r--tex/context/base/mkiv/tabl-xtb.lua10
-rw-r--r--tex/context/base/mkiv/task-ini.lua21
-rw-r--r--tex/context/base/mkiv/toks-ini.lua34
-rw-r--r--tex/context/base/mkiv/toks-ini.mkiv8
-rw-r--r--tex/context/base/mkiv/toks-scn.lua47
-rw-r--r--tex/context/base/mkiv/trac-deb.lua32
-rw-r--r--tex/context/base/mkiv/trac-inf.lua59
-rw-r--r--tex/context/base/mkiv/trac-jus.lua42
-rw-r--r--tex/context/base/mkiv/trac-par.lua16
-rw-r--r--tex/context/base/mkiv/trac-vis.lua1110
-rw-r--r--tex/context/base/mkiv/trac-vis.mkiv2
-rw-r--r--tex/context/base/mkiv/typo-brk.lua105
-rw-r--r--tex/context/base/mkiv/typo-cap.lua146
-rw-r--r--tex/context/base/mkiv/typo-cap.mkiv2
-rw-r--r--tex/context/base/mkiv/typo-cln.lua5
-rw-r--r--tex/context/base/mkiv/typo-dha.lua5
-rw-r--r--tex/context/base/mkiv/typo-dig.lua13
-rw-r--r--tex/context/base/mkiv/typo-dir.lua8
-rw-r--r--tex/context/base/mkiv/typo-drp.lua17
-rw-r--r--tex/context/base/mkiv/typo-dua.lua17
-rw-r--r--tex/context/base/mkiv/typo-dub.lua17
-rw-r--r--tex/context/base/mkiv/typo-duc.lua17
-rw-r--r--tex/context/base/mkiv/typo-fkr.lua4
-rw-r--r--tex/context/base/mkiv/typo-fln.lua14
-rw-r--r--tex/context/base/mkiv/typo-itc.lua29
-rw-r--r--tex/context/base/mkiv/typo-krn.lua111
-rw-r--r--tex/context/base/mkiv/typo-lin.lua38
-rw-r--r--tex/context/base/mkiv/typo-mar.lua35
-rw-r--r--tex/context/base/mkiv/typo-pag.lua28
-rw-r--r--tex/context/base/mkiv/typo-rep.lua9
-rw-r--r--tex/context/base/mkiv/typo-rub.lua236
-rw-r--r--tex/context/base/mkiv/typo-rub.mkiv2
-rw-r--r--tex/context/base/mkiv/typo-spa.lua12
-rw-r--r--tex/context/base/mkiv/typo-sus.lua33
-rw-r--r--tex/context/base/mkiv/typo-tal.lua6
-rw-r--r--tex/context/base/mkiv/typo-wrp.lua10
-rw-r--r--tex/context/base/mkiv/util-fil.lua18
-rw-r--r--tex/context/base/mkiv/util-sbx.lua452
-rw-r--r--tex/context/base/mkiv/util-seq.lua28
-rw-r--r--tex/context/base/mkiv/util-sql-imp-client.lua2
-rw-r--r--tex/context/base/mkiv/util-sql-imp-sqlite.lua1
-rw-r--r--tex/context/fonts/mkiv/cambria-math.lfg9
-rw-r--r--tex/context/fonts/mkiv/type-imp-ebgaramond.mkiv4
-rw-r--r--tex/context/interface/mkii/keys-cs.xml1
-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-fr.xml1
-rw-r--r--tex/context/interface/mkii/keys-it.xml1
-rw-r--r--tex/context/interface/mkii/keys-nl.xml1
-rw-r--r--tex/context/interface/mkii/keys-pe.xml1
-rw-r--r--tex/context/interface/mkii/keys-ro.xml1
-rw-r--r--tex/context/interface/mkiv/i-boxes.xml5
-rw-r--r--tex/context/interface/mkiv/i-context.pdfbin804150 -> 804340 bytes
-rw-r--r--tex/context/interface/mkiv/i-fonts.xml2
-rw-r--r--tex/context/interface/mkiv/i-readme.pdfbin60767 -> 60766 bytes
-rw-r--r--tex/context/modules/mkiv/m-matrix.mkiv94
-rw-r--r--tex/context/modules/mkiv/m-steps.lua1
-rw-r--r--tex/context/modules/mkiv/m-steps.mkvi3
-rw-r--r--tex/context/modules/mkiv/s-inf-03.mkiv6
-rw-r--r--tex/context/modules/mkiv/s-languages-hyphenation.lua10
-rw-r--r--tex/context/sample/common/douglas.tex2
-rw-r--r--tex/context/sample/common/knuth.tex2
-rw-r--r--tex/generic/context/luatex/luatex-basics-nod.lua158
-rw-r--r--tex/generic/context/luatex/luatex-fonts-merged.lua1706
213 files changed, 7898 insertions, 5423 deletions
diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii
index 90d6159a1..f08a0cb1c 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{2017.01.27 14:39}
+\newcontextversion{2017.02.17 10:17}
%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 a1d9a912e..70ca44d90 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{2017.01.27 14:39}
+\edef\contextversion{2017.02.17 10:17}
%D For those who want to use this:
diff --git a/tex/context/base/mkii/mult-cs.mkii b/tex/context/base/mkii/mult-cs.mkii
index 9a0247e5f..837a397fb 100644
--- a/tex/context/base/mkii/mult-cs.mkii
+++ b/tex/context/base/mkii/mult-cs.mkii
@@ -212,6 +212,7 @@
\setinterfacevariable{formulas}{rovnice}
\setinterfacevariable{forward}{vpred}
\setinterfacevariable{four}{ctyri}
+\setinterfacevariable{fractions}{fractions}
\setinterfacevariable{frame}{ramecek}
\setinterfacevariable{framedtext}{oramovanytext}
\setinterfacevariable{friday}{patek}
diff --git a/tex/context/base/mkii/mult-de.mkii b/tex/context/base/mkii/mult-de.mkii
index 1e9f742ca..ec1fb10f4 100644
--- a/tex/context/base/mkii/mult-de.mkii
+++ b/tex/context/base/mkii/mult-de.mkii
@@ -212,6 +212,7 @@
\setinterfacevariable{formulas}{formeln}
\setinterfacevariable{forward}{vorwaerts}
\setinterfacevariable{four}{vier}
+\setinterfacevariable{fractions}{fractions}
\setinterfacevariable{frame}{rahmen}
\setinterfacevariable{framedtext}{umrahmtertext}
\setinterfacevariable{friday}{freitag}
diff --git a/tex/context/base/mkii/mult-en.mkii b/tex/context/base/mkii/mult-en.mkii
index 0af55d772..a4838128b 100644
--- a/tex/context/base/mkii/mult-en.mkii
+++ b/tex/context/base/mkii/mult-en.mkii
@@ -212,6 +212,7 @@
\setinterfacevariable{formulas}{formulas}
\setinterfacevariable{forward}{forward}
\setinterfacevariable{four}{four}
+\setinterfacevariable{fractions}{fractions}
\setinterfacevariable{frame}{frame}
\setinterfacevariable{framedtext}{framedtext}
\setinterfacevariable{friday}{friday}
diff --git a/tex/context/base/mkii/mult-fr.mkii b/tex/context/base/mkii/mult-fr.mkii
index 382e7e059..318bfc31c 100644
--- a/tex/context/base/mkii/mult-fr.mkii
+++ b/tex/context/base/mkii/mult-fr.mkii
@@ -212,6 +212,7 @@
\setinterfacevariable{formulas}{formules}
\setinterfacevariable{forward}{avance}
\setinterfacevariable{four}{quatre}
+\setinterfacevariable{fractions}{fractions}
\setinterfacevariable{frame}{cadre}
\setinterfacevariable{framedtext}{texteencadre}
\setinterfacevariable{friday}{vendredi}
diff --git a/tex/context/base/mkii/mult-it.mkii b/tex/context/base/mkii/mult-it.mkii
index b59842f89..269d1e545 100644
--- a/tex/context/base/mkii/mult-it.mkii
+++ b/tex/context/base/mkii/mult-it.mkii
@@ -212,6 +212,7 @@
\setinterfacevariable{formulas}{formule}
\setinterfacevariable{forward}{avanti}
\setinterfacevariable{four}{quattro}
+\setinterfacevariable{fractions}{fractions}
\setinterfacevariable{frame}{cornice}
\setinterfacevariable{framedtext}{testoincorniciato}
\setinterfacevariable{friday}{venerdi}
diff --git a/tex/context/base/mkii/mult-nl.mkii b/tex/context/base/mkii/mult-nl.mkii
index a88ec0508..30703e4a6 100644
--- a/tex/context/base/mkii/mult-nl.mkii
+++ b/tex/context/base/mkii/mult-nl.mkii
@@ -212,6 +212,7 @@
\setinterfacevariable{formulas}{formules}
\setinterfacevariable{forward}{vooruit}
\setinterfacevariable{four}{vier}
+\setinterfacevariable{fractions}{fractions}
\setinterfacevariable{frame}{kader}
\setinterfacevariable{framedtext}{kadertekst}
\setinterfacevariable{friday}{vrijdag}
diff --git a/tex/context/base/mkii/mult-pe.mkii b/tex/context/base/mkii/mult-pe.mkii
index 3203a0ffb..8b300ae73 100644
--- a/tex/context/base/mkii/mult-pe.mkii
+++ b/tex/context/base/mkii/mult-pe.mkii
@@ -212,6 +212,7 @@
\setinterfacevariable{formulas}{فرمولها}
\setinterfacevariable{forward}{به‌جلو}
\setinterfacevariable{four}{چهار}
+\setinterfacevariable{fractions}{fractions}
\setinterfacevariable{frame}{قالب}
\setinterfacevariable{framedtext}{متن‌قالبی}
\setinterfacevariable{friday}{جمعه}
diff --git a/tex/context/base/mkii/mult-ro.mkii b/tex/context/base/mkii/mult-ro.mkii
index 41ccfc8ed..26d0cd9c6 100644
--- a/tex/context/base/mkii/mult-ro.mkii
+++ b/tex/context/base/mkii/mult-ro.mkii
@@ -212,6 +212,7 @@
\setinterfacevariable{formulas}{formule}
\setinterfacevariable{forward}{avans}
\setinterfacevariable{four}{patru}
+\setinterfacevariable{fractions}{fractions}
\setinterfacevariable{frame}{incadrat}
\setinterfacevariable{framedtext}{textinconjurat}
\setinterfacevariable{friday}{vineri}
diff --git a/tex/context/base/mkiv/anch-bck.mkvi b/tex/context/base/mkiv/anch-bck.mkvi
index 3bd8cfb4b..1bd855203 100644
--- a/tex/context/base/mkiv/anch-bck.mkvi
+++ b/tex/context/base/mkiv/anch-bck.mkvi
@@ -588,6 +588,19 @@
\includeMPgraphic{mpos:region:anchor} ;
\stopMPpositiongraphic
+%D For old times sake:
+
+\startMPpositiongraphic{mpos:box}{fillcolor,linecolor,linewidth}
+ string tag; tag := "\MPvar{self}" ;
+ path box ; box := positionbox(tag) ;
+
+ box := box enlarged \MPvar{filloffset} ;
+ fill box withcolor \MPvar{fillcolor} ;
+ draw box withcolor \MPvar{linecolor} withpen pencircle scaled \MPvar{linewidth} ;
+
+ positioninregion;
+\stopMPpositiongraphic
+
\startMPpositionmethod{mpos:region}
\MPpositiongraphic{mpos:region}{}%
\stopMPpositionmethod
diff --git a/tex/context/base/mkiv/anch-pgr.lua b/tex/context/base/mkiv/anch-pgr.lua
index 468b9eee3..6a2912024 100644
--- a/tex/context/base/mkiv/anch-pgr.lua
+++ b/tex/context/base/mkiv/anch-pgr.lua
@@ -17,7 +17,7 @@ if not modules then modules = { } end modules ['anch-pgr'] = {
-- will discuss this issue.
local abs, div, floor, round = math.abs, math.div, math.floor, math.round
-local concat, sort, copy = table.concat, table.sort, table.copy
+local concat = table.concat
local splitter = lpeg.splitat(":")
local lpegmatch = lpeg.match
@@ -46,7 +46,7 @@ local f_tag_two = formatters["%s:%s"]
local f_point = formatters["%p"]
local f_pair = formatters["(%p,%p)"]
local f_path = formatters["%--t--cycle"]
-local f_pair_i = formatters["(%i,%i)"]
+local f_pair_i = formatters["(%r,%r)"] -- rounded
graphics = graphics or { }
local backgrounds = { }
@@ -55,7 +55,6 @@ graphics.backgrounds = backgrounds
-- -- --
local texsetattribute = tex.setattribute
-local texgetcount = tex.getcount
local pdfgetpos = pdf.getpos -- why not a generic name !
local a_textbackground = attributes.private("textbackground")
@@ -72,8 +71,7 @@ local insert_after = nuts.insert_after
local processranges = nodes.processranges
-local v_yes = interfaces.variables.yes
-local v_always = interfaces.variables.always
+local unsetvalue = attributes.unsetvalue
local jobpositions = job.positions
@@ -107,7 +105,7 @@ local function registerbackground(name)
texsetattribute(a_textbackground,n)
enabled = true
else
- texsetattribute(a_textbackground,attributes.unsetvalue)
+ texsetattribute(a_textbackground,unsetvalue)
end
end
diff --git a/tex/context/base/mkiv/anch-pos.lua b/tex/context/base/mkiv/anch-pos.lua
index 72d76301c..848b42d41 100644
--- a/tex/context/base/mkiv/anch-pos.lua
+++ b/tex/context/base/mkiv/anch-pos.lua
@@ -65,9 +65,7 @@ local getbox = nuts.getbox
local getid = nuts.getid
local getwhd = nuts.getwhd
-local n_flush_node = nodes.flush
-
-local hlist_code = nodes.listcodes.hlist
+----- hlist_code = nodes.listcodes.hlist
local find_tail = nuts.tail
@@ -783,6 +781,13 @@ function jobpositions.depth(id)
return jpi and jpi.d
end
+function jobpositions.whd(id)
+ local jpi = collected[id]
+ if jpi then
+ return jpi.h, jpi.h, jpi.d
+ end
+end
+
function jobpositions.leftskip(id)
local jpi = collected[id]
return jpi and jpi.ls
diff --git a/tex/context/base/mkiv/attr-col.lua b/tex/context/base/mkiv/attr-col.lua
index 2562eb944..3cd712449 100644
--- a/tex/context/base/mkiv/attr-col.lua
+++ b/tex/context/base/mkiv/attr-col.lua
@@ -47,11 +47,13 @@ local report_transparencies = logs.reporter("transparencies","support")
-- nb. too many "0 g"s
local states = attributes.states
-local tasks = nodes.tasks
local nodeinjections = backends.nodeinjections
local registrations = backends.registrations
local unsetvalue = attributes.unsetvalue
+local enableaction = nodes.tasks.enableaction
+local setaction = nodes.tasks.setaction
+
local registerstorage = storage.register
local formatters = string.formatters
@@ -170,9 +172,9 @@ end
-- http://en.wikipedia.org/wiki/HSI_color_space
-- http://nl.wikipedia.org/wiki/HSV_(kleurruimte)
--- h /= 60; // sector 0 to 5
+-- h /= 60; // sector 0 to 5
-- i = floor( h );
--- f = h - i; // factorial part of h
+-- f = h - i; // factorial part of h
local function hsvtorgb(h,s,v)
if s > 1 then
@@ -437,11 +439,7 @@ attributes.colors.handler = nodes.installattributehandler {
}
function colors.enable(value)
- if value == false or not colors.supported then
- tasks.disableaction("shipouts","attributes.colors.handler")
- else
- tasks.enableaction("shipouts","attributes.colors.handler")
- end
+ setaction("shipouts","attributes.colors.handler",not (value == false or not colors.supported))
end
function colors.forcesupport(value) -- can move to attr-div
@@ -547,11 +545,7 @@ attributes.transparencies.handler = nodes.installattributehandler {
}
function transparencies.enable(value) -- nil is enable
- if value == false or not transparencies.supported then
- tasks.disableaction("shipouts","attributes.transparencies.handler")
- else
- tasks.enableaction("shipouts","attributes.transparencies.handler")
- end
+ setaction("shipouts","attributes.transparencies.handler",not (value == false or not transparencies.supported))
end
function transparencies.forcesupport(value) -- can move to attr-div
@@ -610,7 +604,7 @@ colorintents.handler = nodes.installattributehandler {
}
function colorintents.enable()
- tasks.enableaction("shipouts","attributes.colorintents.handler")
+ enableaction("shipouts","attributes.colorintents.handler")
end
-- interface
diff --git a/tex/context/base/mkiv/attr-eff.lua b/tex/context/base/mkiv/attr-eff.lua
index ff41e12de..d04408fb9 100644
--- a/tex/context/base/mkiv/attr-eff.lua
+++ b/tex/context/base/mkiv/attr-eff.lua
@@ -10,7 +10,7 @@ local attributes, nodes, backends, utilities = attributes, nodes, backends, util
local tex = tex
local states = attributes.states
-local tasks = nodes.tasks
+local enableaction = nodes.tasks.enableaction
local nodeinjections = backends.nodeinjections
local texsetattribute = tex.setattribute
local allocate = utilities.storage.allocate
@@ -97,7 +97,7 @@ local enabled = false
local function enable()
if not enabled then
- tasks.enableaction("shipouts","attributes.effects.handler")
+ enableaction("shipouts","attributes.effects.handler")
enabled = true
end
end
diff --git a/tex/context/base/mkiv/attr-ini.mkiv b/tex/context/base/mkiv/attr-ini.mkiv
index a2d37118b..77959c988 100644
--- a/tex/context/base/mkiv/attr-ini.mkiv
+++ b/tex/context/base/mkiv/attr-ini.mkiv
@@ -40,6 +40,7 @@
\newtoks \t_attr_list_global
\newtoks \t_attr_list_local
+\newtoks \t_attr_list_nomath
\ifdefined \s!global \else \def\s!global {global} \fi % for metatex % or hard check later
\ifdefined \s!public \else \def\s!public {public} \fi % for metatex % or hard check later
@@ -63,6 +64,8 @@
\doifelseinset\s!global{#3}%
{\appendetoks\csname\??attributecount#2\endcsname\attributeunsetvalue\to\t_attr_list_global}%
{\appendetoks\csname\??attributecount#2\endcsname\attributeunsetvalue\to\t_attr_list_local }%
+ \doifinset\s!nomath{#3}%
+ {\appendetoks\csname\??attributecount#2\endcsname\attributeunsetvalue\to\t_attr_list_nomath}%
% here public means 'visible' so it's not to be confused with 'public' at the lua end
\doifinset\s!public{#3}%
{\expandafter\let\csname#2\s!attribute\expandafter\endcsname\csname\??attributeid#2\endcsname}%
@@ -91,23 +94,27 @@
\unexpanded\def\savecurrentattributes #1{\clf_savecurrentattributes {#1}}
\unexpanded\def\restorecurrentattributes#1{\clf_restorecurrentattributes{#1}}
-%D For the moment we put this here (later it will move to where it's used):
+%D For the moment we put this here. The order of definition matters a bit because
+%D performance is better when we put frequently accessed attributes at the front.
+%D So, we might move more here.
-\definesystemattribute [state]
-\definesystemattribute [color] [public] % global
+\definesystemattribute [state] % nomath
+\definesystemattribute [color] [public] % global
\definesystemattribute [colormodel] [public,global]
-\definesystemattribute [skip]
-\definesystemattribute [penalty]
+% \definesystemattribute [skip]
+% \definesystemattribute [penalty]
\definesystemattribute [transparency] [public]
+\definesystemattribute [reference] [public]
+\definesystemattribute [destination] [public]
+\definesystemattribute [case] [public]
+\definesystemattribute [visual] [public,global]
+\definesystemattribute [viewerlayer] [public]
\definesystemattribute [background] [public]
\definesystemattribute [alignbackground] [public]
\definesystemattribute [colorintent] [public]
\definesystemattribute [negative] [public]
\definesystemattribute [effect] [public]
-\definesystemattribute [viewerlayer] [public]
\definesystemattribute [layoutcomponent] [public]
-\definesystemattribute [reference] [public]
-\definesystemattribute [destination] [public]
\definesystemattribute [internal] [public]
\definesystemattribute [ruled] [public]
\definesystemattribute [shifted] [public]
diff --git a/tex/context/base/mkiv/attr-lay.lua b/tex/context/base/mkiv/attr-lay.lua
index 051ff6e10..ff9d1c38f 100644
--- a/tex/context/base/mkiv/attr-lay.lua
+++ b/tex/context/base/mkiv/attr-lay.lua
@@ -62,7 +62,8 @@ viewerlayers.supported = true
viewerlayers.hasorder = true
local states = attributes.states
-local tasks = nodes.tasks
+local enableaction = nodes.tasks.enableaction
+local disableaction = nodes.tasks.disableaction
local nodeinjections = backends.nodeinjections
local codeinjections = backends.codeinjections
@@ -146,12 +147,12 @@ local stack, enabled, global = { }, false, false
function viewerlayers.enable(value)
if value == false or not viewerlayers.supported then
if enabled then
- tasks.disableaction("shipouts","attributes.viewerlayers.handler")
+ disableaction("shipouts","attributes.viewerlayers.handler")
end
enabled = false
else
if not enabled then
- tasks.enableaction("shipouts","attributes.viewerlayers.handler")
+ enableaction("shipouts","attributes.viewerlayers.handler")
end
enabled = true
end
diff --git a/tex/context/base/mkiv/attr-neg.lua b/tex/context/base/mkiv/attr-neg.lua
index 1347c3d1a..c20df1d16 100644
--- a/tex/context/base/mkiv/attr-neg.lua
+++ b/tex/context/base/mkiv/attr-neg.lua
@@ -16,7 +16,7 @@ local commands, context, interfaces = commands, context, interfaces
local tex = tex
local states = attributes.states
-local tasks = nodes.tasks
+local enableaction = nodes.tasks.enableaction
local nodeinjections = backends.nodeinjections
local texsetattribute = tex.setattribute
local variables = interfaces.variables
@@ -79,7 +79,7 @@ local function register(stamp)
end
local function enable()
- tasks.enableaction("shipouts","attributes.negatives.handler")
+ enableaction("shipouts","attributes.negatives.handler")
end
negatives.register = register
diff --git a/tex/context/base/mkiv/back-exp.lua b/tex/context/base/mkiv/back-exp.lua
index bd87075d0..da7ec202f 100644
--- a/tex/context/base/mkiv/back-exp.lua
+++ b/tex/context/base/mkiv/back-exp.lua
@@ -118,12 +118,16 @@ local getnext = nuts.getnext
local getsubtype = nuts.getsubtype
local getfont = nuts.getfont
local getdisc = nuts.getdisc
+local getcomponents = nuts.getcomponents
local getlist = nuts.getlist
local getid = nuts.getid
local getfield = nuts.getfield
local getattr = nuts.getattr
local setattr = nuts.setattr -- maybe use properties
local isglyph = nuts.isglyph
+local getkern = nuts.getkern
+local getwidth = nuts.getwidth
+
local traverse_id = nuts.traverse_id
local traverse_nodes = nuts.traverse
@@ -544,27 +548,6 @@ local function makebreaknode(attributes) -- maybe no fulltag
}
end
-local function ignorebreaks(di,element,n,fulltag)
- local data = di.data
- for i=1,#data do
- local d = data[i]
- if d.content == " " then
- d.content = ""
- end
- end
-end
-
-local function ignorespaces(di,element,n,fulltag)
- local data = di.data
- for i=1,#data do
- local d = data[i]
- local c = d.content
- if type(c) == "string" then
- d.content = lpegmatch(p_stripper,c)
- end
- end
-end
-
do
local fields = { "title", "subtitle", "author", "keywords" }
@@ -1719,6 +1702,27 @@ do
end
end
+ local function ignorebreaks(di,element,n,fulltag)
+ local data = di.data
+ for i=1,#data do
+ local d = data[i]
+ if d.content == " " then
+ d.content = ""
+ end
+ end
+ end
+
+ local function ignorespaces(di,element,n,fulltag)
+ local data = di.data
+ for i=1,#data do
+ local d = data[i]
+ local c = d.content
+ if type(c) == "string" then
+ d.content = lpegmatch(p_stripper,c)
+ end
+ end
+ end
+
extras.registerpages = ignorebreaks
extras.registerseparator = ignorespaces
@@ -2549,7 +2553,7 @@ local function collectresults(head,list,pat,pap) -- is last used (we also have c
-- report_export("skipping character: %C (no attribute)",n.char)
else
-- we could add tonunicodes for ligatures (todo)
- local components = getfield(n,"components")
+ local components = getcomponents(n)
if components and (not characterdata[c] or overloads[c]) then -- we loose data
collectresults(components,nil,at) -- this assumes that components have the same attribute as the glyph ... we should be more tolerant (see math)
else
@@ -2699,7 +2703,7 @@ local function collectresults(head,list,pat,pap) -- is last used (we also have c
else
local subtype = getsubtype(n)
if subtype == userskip_code then
- if getfield(n,"width") > threshold then
+ if getwidth(n) > threshold then
if last and not somespace[currentcontent[nofcurrentcontent]] then
local a = getattr(n,a_tagged) or pat
if a == last then
@@ -2807,7 +2811,7 @@ local function collectresults(head,list,pat,pap) -- is last used (we also have c
end
end
elseif id == kern_code then
- local kern = getfield(n,"kern")
+ local kern = getkern(n)
if kern > 0 then
local limit = threshold
if p and getid(p) == glyph_code then
diff --git a/tex/context/base/mkiv/back-ini.lua b/tex/context/base/mkiv/back-ini.lua
index fc0074540..fd33d5ddc 100644
--- a/tex/context/base/mkiv/back-ini.lua
+++ b/tex/context/base/mkiv/back-ini.lua
@@ -16,15 +16,15 @@ if not modules then modules = { } end modules ['back-ini'] = {
local next, type = next, type
local format = string.format
-backends = backends or { }
-local backends = backends
+backends = backends or { }
+local backends = backends
-local trace_backend = false trackers.register("backend.initializers", function(v) trace_finalizers = v end)
-
-local report_backend = logs.reporter("backend","initializing")
+local trace_backend = false trackers.register("backend.initializers", function(v) trace_finalizers = v end)
+local report_backend = logs.reporter("backend","initializing")
local allocate = utilities.storage.allocate
local setmetatableindex = table.setmetatableindex
+local setaction = nodes.tasks.setaction
local function nothing() return nil end
@@ -117,7 +117,7 @@ interfaces.implement {
name = "setrealspaces",
arguments = "string",
actions = function(v)
- nodes.tasks.setaction("shipouts","nodes.handlers.accessibility",v == interfaces.variables.yes)
+ setaction("shipouts","nodes.handlers.accessibility",v == interfaces.variables.yes)
end
}
diff --git a/tex/context/base/mkiv/back-pdf.lua b/tex/context/base/mkiv/back-pdf.lua
index b6633f091..a3f7ffff7 100644
--- a/tex/context/base/mkiv/back-pdf.lua
+++ b/tex/context/base/mkiv/back-pdf.lua
@@ -19,6 +19,9 @@ local context = context
local scanners = tokens.scanners
local scannumber = scanners.number
local scankeyword = scanners.keyword
+local scandimen = scanners.dimen
+local scancount = scanners.count
+local scanstring = scanners.string
local scanners = interfaces.scanners
local implement = interfaces.implement
@@ -178,3 +181,136 @@ implement {
pdf.setobjcompresslevel(o)
end
}
+
+local report = logs.reporter("backend","pdftex primitives")
+local trace = false
+
+scanners.pdfannot = function()
+ if scankeyword("reserveobjectnum") then
+ report("\\pdfannot reserveobjectnum is not (yet) supported")
+ -- if trace then
+ -- report()
+ -- report("\\pdfannot: reserved number (not supported yet)")
+ -- report()
+ -- end
+ else
+ local width = false
+ local height = false
+ local depth = false
+ local data = false
+ local object = false
+ local attr = false
+ --
+ if scankeyword("useobjnum") then
+ object = scancount()
+ report("\\pdfannot useobjectnum is not (yet) supported")
+ end
+ while true do
+ if scankeyword("width") then
+ width = scandimen()
+ elseif scankeyword("height") then
+ height = scandimen()
+ elseif scankeyword("depth") then
+ depth = scandimen()
+ else
+ break
+ end
+ end
+ if scankeyword("attr") then
+ attr = scanstring()
+ end
+ data = scanstring()
+ --
+ -- less strict variant:
+ --
+ -- while true do
+ -- if scankeyword("width") then
+ -- width = scandimen()
+ -- elseif scankeyword("height") then
+ -- height = scandimen()
+ -- elseif scankeyword("depth") then
+ -- depth = scandimen()
+ -- elseif scankeyword("useobjnum") then
+ -- object = scancount()
+ -- elseif scankeyword("attr") then
+ -- attr = scanstring()
+ -- else
+ -- data = scanstring()
+ -- break
+ -- end
+ -- end
+ --
+ -- if trace then
+ -- report()
+ -- report("\\pdfannot:")
+ -- report()
+ -- report(" object: %s",object or "<unset> (not supported yet)")
+ -- report(" width : %p",width or "<unset>")
+ -- report(" height: %p",height or "<unset>")
+ -- report(" depth : %p",depth or "<unset>")
+ -- report(" attr : %s",attr or "<unset>")
+ -- report(" data : %s",data or "<unset>")
+ -- report()
+ -- end
+ context(backends.nodeinjections.annotation(width or 0,height or 0,depth or 0,data or ""))
+ end
+end
+
+scanners.pdfdest = function()
+ local name = false
+ local zoom = false
+ local view = false
+ local width = false
+ local height = false
+ local depth = false
+ if scankeyword("num") then
+ report("\\pdfdest num is not (yet) supported")
+ elseif scankeyword("name") then
+ name = scanstring()
+ end
+ if scankeyword("xyz") then
+ view = "xyz"
+ if scankeyword("zoom") then
+ report("\\pdfdest zoom is ignored")
+ zoom = scancount()
+ end
+ elseif scankeyword("fitbh") then
+ view = "fitbh"
+ elseif scankeyword("fitbv") then
+ view = "fitbv"
+ elseif scankeyword("fitb") then
+ view = "fitb"
+ elseif scankeyword("fith") then
+ view = "fith"
+ elseif scankeyword("fitv") then
+ view = "fitv"
+ elseif scankeyword("fitr") then
+ view = "fitr"
+ while true do
+ if scankeyword("width") then
+ width = scandimen()
+ elseif scankeyword("height") then
+ height = scandimen()
+ elseif scankeyword("depth") then
+ depth = scandimen()
+ else
+ break
+ end
+ end
+ elseif scankeyword("fit") then
+ view = "fit"
+ end
+ -- if trace then
+ -- report()
+ -- report("\\pdfdest:")
+ -- report()
+ -- report(" name : %s",name or "<unset>")
+ -- report(" view : %s",view or "<unset>")
+ -- report(" zoom : %s",zoom or "<unset> (not supported)")
+ -- report(" width : %p",width or "<unset>")
+ -- report(" height: %p",height or "<unset>")
+ -- report(" depth : %p",depth or "<unset>")
+ -- report()
+ -- end
+ context(backends.nodeinjections.destination(width or 0,height or 0,depth or 0,{ name or "" },view or "fit"))
+end
diff --git a/tex/context/base/mkiv/back-pdf.mkiv b/tex/context/base/mkiv/back-pdf.mkiv
index 84e58d84c..f59b59c29 100644
--- a/tex/context/base/mkiv/back-pdf.mkiv
+++ b/tex/context/base/mkiv/back-pdf.mkiv
@@ -52,31 +52,37 @@
%D These are no-ops and don't even intercept what comes next. Maybe some day
%D I'll write a parser that maps onto \CONTEXT.
-\let\pdfcolorstack \relax
-\let\pdfcolorstackinit \relax
-\let\pdfannot \relax
-\let\pdfstartlink \relax
-\let\pdfendlink \relax
-\let\pdfoutline \relax
-\let\pdfdest \relax
-\let\pdfthread \relax
-\let\pdfstartthread \relax
-\let\pdfendthread \relax
-\let\pdffontattr \relax
-\let\pdfglyphtounicode \relax
+\unexpanded\def\unsupportedpdfprimitive#1%
+ {\writestatus{error}{the primitive \string#1\space is not supported}}
+
+\unexpanded\def\pdfcolorstack {\unsupportedpdfprimitive\pdfcolorstack}
+\unexpanded\def\pdfcolorstackinit{\unsupportedpdfprimitive\pdfcolorstackinit}
+%unexpanded\def\pdfannot {\unsupportedpdfprimitive\pdfannot}
+\unexpanded\def\pdfstartlink {\unsupportedpdfprimitive\pdfstartlink}
+\unexpanded\def\pdfendlink {\unsupportedpdfprimitive\pdfendlink}
+\unexpanded\def\pdfoutline {\unsupportedpdfprimitive\pdfoutline}
+%unexpanded\def\pdfdest {\unsupportedpdfprimitive\pdfdest}
+\unexpanded\def\pdfthread {\unsupportedpdfprimitive\pdfthread}
+\unexpanded\def\pdfstartthread {\unsupportedpdfprimitive\pdfstartthread}
+\unexpanded\def\pdfendthread {\unsupportedpdfprimitive\pdfendthread}
+\unexpanded\def\pdffontattr {\unsupportedpdfprimitive\pdffontattr}
+\unexpanded\def\pdfglyphtounicode{\unsupportedpdfprimitive\pdfglyphtounicode}
+
+\unexpanded\def\pdfannot{\clf_pdfannot}
+\unexpanded\def\pdfdest {\clf_pdfdest}
%D Here we do intercept (silently) what gets passed. One should use the
%D \CONTEXT\ interfaces instead.
-\let\pdfcatalog \relax \newtoks \pdfcatalog
-\let\pdfinfo \relax \newtoks \pdfinfo
-\let\pdfnames \relax \newtoks \pdfnames
-\let\pdftrailer \relax \newtoks \pdftrailer
-\let\pdfpageresources \relax \newtoks \pdfpageresources
-\let\pdfpageattr \relax \newtoks \pdfpageattr
-\let\pdfpagesattr \relax \newtoks \pdfpagesattr
-\let\pdfxformattr \relax \newtoks \pdfxformattr
-\let\pdfxformresources \relax \newtoks \pdfxformresources
+\let\pdfcatalog \relax \newtoks\pdfcatalog
+\let\pdfinfo \relax \newtoks\pdfinfo
+\let\pdfnames \relax \newtoks\pdfnames
+\let\pdftrailer \relax \newtoks\pdftrailer
+\let\pdfpageresources \relax \newtoks\pdfpageresources
+\let\pdfpageattr \relax \newtoks\pdfpageattr
+\let\pdfpagesattr \relax \newtoks\pdfpagesattr
+\let\pdfxformattr \relax \newtoks\pdfxformattr
+\let\pdfxformresources\relax \newtoks\pdfxformresources
%D We use the \LUA\ interface (which then permits more control over
%D possible pdf/x extensions).
@@ -588,3 +594,14 @@
% \stoptext
\protect \endinput
+
+% \chapter{FIRST}
+%
+% \goto{bar}[bar]
+%
+% HERE \pdfannot width 20pt height 20pt depth 20pt {/Subtype /Link /Dest (bar) /Border [1 1 1] /F 4}\par
+% HERE \pdfannot width 20pt height 20pt depth 20pt {/Subtype /Link /Dest (foo) /Border [1 1 1] /F 4}\par
+%
+% \chapter[bar]{SECOND}
+%
+% THERE \pdfdest name {foo} \par
diff --git a/tex/context/base/mkiv/bibl-tra.lua b/tex/context/base/mkiv/bibl-tra.lua
index 223554b4d..76171cb7f 100644
--- a/tex/context/base/mkiv/bibl-tra.lua
+++ b/tex/context/base/mkiv/bibl-tra.lua
@@ -21,7 +21,9 @@ end
-- end of hack
-local match, gmatch, format, concat, sort = string.match, string.gmatch, string.format, table.concat, table.sort
+local gmatch, format = string.gmatch, string.format
+local sort = table.sort
+local savedata = io.savedata
bibtex = bibtex or { }
local bibtex = bibtex
@@ -61,10 +63,31 @@ local template = [[
\bibdata{%s}
]]
-local bibtexbin = environment.arguments.mlbibtex and "mlbibcontext" or "bibtex"
+local runners = {
+ bibtex = sandbox.registerrunner {
+ name = "bibtex",
+ method = "execute",
+ program = "bibtex",
+ template = [["%filename%"]],
+ checkers = {
+ filename = "readable",
+ }
+ },
+ mlbibtex = sandbox.registerrunner {
+ name = "mlbibtex",
+ method = "execute",
+ program = "mlbibcontext",
+ template = [["%filename%"]],
+ checkers = {
+ filename = "readable",
+ }
+ }
+}
+
+local runner = environment.arguments.mlbibtex and runners.mlbibtex or runners.bibtex
directives.register("publications.usemlbibtex", function(v)
- bibtexbin = v and "mlbibcontext" or "bibtex"
+ runner = v and runners.mlbibtex or runners.bibtex
end)
function hacks.process(settings)
@@ -74,11 +97,11 @@ function hacks.process(settings)
if database ~= "" then
local targetfile = file.addsuffix(jobname,"aux")
interfaces.showmessage("publications",3,targetfile)
- io.savedata(targetfile,format(template,style,database))
+ savedata(targetfile,format(template,style,database))
if trace_bibtex then
report_tex("processing bibtex file %a using %a",jobname,bibtexbin)
end
- os.execute(format("%s %q",bibtexbin,jobname))
+ runner { filename = jobname }
-- purge 'm
end
end
diff --git a/tex/context/base/mkiv/buff-ini.lua b/tex/context/base/mkiv/buff-ini.lua
index 876a6944e..2b3270300 100644
--- a/tex/context/base/mkiv/buff-ini.lua
+++ b/tex/context/base/mkiv/buff-ini.lua
@@ -12,6 +12,7 @@ local sub, format = string.sub, string.format
local splitlines, validstring, replacenewlines = string.splitlines, string.valid, string.replacenewlines
local P, Cs, patterns, lpegmatch = lpeg.P, lpeg.Cs, lpeg.patterns, lpeg.match
local utfchar = utf.char
+local nameonly = file.nameonly
local totable = string.totable
local trace_run = false trackers.register("buffers.run", function(v) trace_run = v end)
@@ -486,6 +487,17 @@ implement {
local oldhashes = nil
local newhashes = nil
+local runner = sandbox.registerrunner {
+ name = "run buffer",
+ program = "context",
+ method = "execute",
+ template = "--purgeall " .. (jit and "--jit" or "") .. " %filename%",
+ reporter = report_typeset,
+ checkers = {
+ filename = "readable",
+ }
+}
+
local function runbuffer(name,encapsulate)
if not oldhashes then
oldhashes = job.datasets.getdata("typeset buffers","hashes") or { }
@@ -513,7 +525,7 @@ local function runbuffer(name,encapsulate)
end
--
local hash = md5.hex(content)
- local tag = formatters["%s-t-b-%s"](tex.jobname,hash)
+ local tag = formatters["%s-t-b-%s"](nameonly(tex.jobname),hash) -- make sure we run on the local path
--
local filename = addsuffix(tag,"tmp")
local resultname = addsuffix(tag,"pdf")
@@ -525,9 +537,8 @@ local function runbuffer(name,encapsulate)
report_typeset("changes in %a, processing forced",name)
end
io.savedata(filename,content)
- local command = formatters["context --purgeall %s %s"](jit and "--jit" or "",filename)
- report_typeset("running: %s\n",command)
- os.execute(command)
+ report_typeset("processing saved buffer %a\n",filename)
+ runner { filename = filename }
end
newhashes[hash] = (newhashes[hash] or 0) + 1
report_typeset("no changes in %a, processing skipped",name)
diff --git a/tex/context/base/mkiv/cldf-ini.lua b/tex/context/base/mkiv/cldf-ini.lua
index 66582ae4f..b0b731866 100644
--- a/tex/context/base/mkiv/cldf-ini.lua
+++ b/tex/context/base/mkiv/cldf-ini.lua
@@ -100,7 +100,7 @@ local flushdirect = texprint -- lines
local report_context = logs.reporter("cld","tex")
local report_cld = logs.reporter("cld","stack")
-local report_template = logs.reporter("cld","template")
+----- report_template = logs.reporter("cld","template")
local processlines = true -- experiments.register("context.processlines", function(v) processlines = v end)
diff --git a/tex/context/base/mkiv/colo-imp-solarized.mkiv b/tex/context/base/mkiv/colo-imp-solarized.mkiv
new file mode 100644
index 000000000..872e6b701
--- /dev/null
+++ b/tex/context/base/mkiv/colo-imp-solarized.mkiv
@@ -0,0 +1,38 @@
+%D \module
+%D [ file=colo-imp-solarized,
+%D version=2017.02.10,
+%D title=\CONTEXT\ Color Macros,
+%D subtitle=Solarized,
+%D author=Aditya Mahajan,
+%D ]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA, See mreadme.pdf for
+%C details.
+
+%D Colors based on solarized scheme:
+%D
+%D \hyphenatedurl{http://ethanschoonover.com/solarized}
+
+\startprotectedcolors
+
+ \definecolor [base03] [h=002b36]
+ \definecolor [base02] [h=073642]
+ \definecolor [base01] [h=586e75]
+ \definecolor [base00] [h=657b83]
+ \definecolor [base0] [h=839496]
+ \definecolor [base1] [h=93a1a1]
+ \definecolor [base2] [h=eee8d5]
+ \definecolor [base3] [h=fdf6e3]
+ \definecolor [yellow] [h=b58900]
+ \definecolor [orange] [h=cb4b16]
+ \definecolor [red] [h=dc322f]
+ \definecolor [magenta] [h=d33682]
+ \definecolor [violet] [h=6c71c4]
+ \definecolor [blue] [h=268bd2]
+ \definecolor [cyan] [h=2aa198]
+ \definecolor [green] [h=859900]
+
+\stopprotectedcolors
+
+\endinput
diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv
index 5b9050d6c..e83b97c3a 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{2017.01.27 14:39}
+\newcontextversion{2017.02.17 10:17}
%D This file is loaded at runtime, thereby providing an excellent place for
%D hacks, patches, extensions and new features.
diff --git a/tex/context/base/mkiv/cont-run.lua b/tex/context/base/mkiv/cont-run.lua
index 0420ed01c..d9dad3f2d 100644
--- a/tex/context/base/mkiv/cont-run.lua
+++ b/tex/context/base/mkiv/cont-run.lua
@@ -90,7 +90,7 @@ local function logsandbox(details)
end
end
-local ioopen = sandbox.original(io.open)
+local ioopen = sandbox.original(io.open) -- dummy call
local function logsandboxfiles(name,what,asked,okay)
-- we're only interested in permitted access
@@ -161,14 +161,13 @@ if sandboxing then
-- Nicer would be if we could just disable write 18 and keep os.execute
-- which in fact we can do by defining write18 as macro instead of
- -- primitive ... todo.
+ -- primitive ... todo ... well, it has been done now.
-- We block some potential escapes from protection.
context [[
\let\primitive \relax
\let\normalprimitive\relax
- \let\normalwrite \relax
]]
end
diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv
index e92a39cbd..e8aae9575 100644
--- a/tex/context/base/mkiv/context.mkiv
+++ b/tex/context/base/mkiv/context.mkiv
@@ -39,7 +39,7 @@
%D up and the dependencies are more consistent.
\edef\contextformat {\jobname}
-\edef\contextversion{2017.01.27 14:39}
+\edef\contextversion{2017.02.17 10:17}
\edef\contextkind {beta}
%D For those who want to use this:
diff --git a/tex/context/base/mkiv/core-con.lua b/tex/context/base/mkiv/core-con.lua
index 36f1774e9..10f8fc2ed 100644
--- a/tex/context/base/mkiv/core-con.lua
+++ b/tex/context/base/mkiv/core-con.lua
@@ -81,6 +81,14 @@ local counters = allocate {
0x0074, 0x0075, 0x0076, 0x0077, 0x0078,
0x0079, 0x007A
},
+ ['russian'] = {
+ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434,
+ 0x0435, 0x0436, 0x0437, 0x0438, 0x043a,
+ 0x043b, 0x043c, 0x043d, 0x043e, 0x043f,
+ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444,
+ 0x0445, 0x0446, 0x0447, 0x0448, 0x0449,
+ 0x044d, 0x044e, 0x044f
+ },
['greek'] = { -- this should be the lowercase table
-- 0x0391, 0x0392, 0x0393, 0x0394, 0x0395,
-- 0x0396, 0x0397, 0x0398, 0x0399, 0x039A,
@@ -153,6 +161,7 @@ counters['gr'] = counters['greek']
counters['g'] = counters['greek']
counters['sl'] = counters['slovenian']
counters['es'] = counters['spanish']
+counters['ru'] = counters['russian']
counters['kr'] = counters['korean']
counters['kr-p'] = counters['korean-parenthesis']
counters['kr-c'] = counters['korean-circle']
@@ -172,6 +181,7 @@ counters['koreancirclenumerals'] = counters['korean-circle']
counters['sloveniannumerals'] = counters['slovenian']
counters['spanishnumerals'] = counters['spanish']
+counters['russiannumerals'] = counters['russian']
local decimals = allocate {
['arabic'] = {
@@ -589,23 +599,29 @@ converters['A'] = converters.Characters
converters['AK'] = converters.Characters -- obsolete
converters['KA'] = converters.Characters -- obsolete
-function converters.spanishnumerals(n) return alphabetic(n,"es") end
-function converters.Spanishnumerals(n) return Alphabetic(n,"es") end
-function converters.sloviannumerals(n) return alphabetic(n,"sl") end
-function converters.Sloviannumerals(n) return Alphabetic(n,"sl") end
+function converters.spanishnumerals (n) return alphabetic(n,"es") end
+function converters.Spanishnumerals (n) return Alphabetic(n,"es") end
+function converters.sloveniannumerals(n) return alphabetic(n,"sl") end
+function converters.Sloveniannumerals(n) return Alphabetic(n,"sl") end
+function converters.russiannumerals (n) return alphabetic(n,"ru") end
+function converters.Russiannumerals (n) return Alphabetic(n,"ru") end
converters['alphabetic:es'] = converters.spanishnumerals
converters['alphabetic:sl'] = converters.sloveniannumerals
+converters['alphabetic:ru'] = converters.russiannumerals
converters['Alphabetic:es'] = converters.Spanishnumerals
converters['Alphabetic:sl'] = converters.Sloveniannumerals
+converters['Alphabetic:ru'] = converters.Russiannumerals
-- bonus
converters['a:es'] = converters.spanishnumerals
converters['a:sl'] = converters.sloveniannumerals
+converters['a:ru'] = converters.russiannumerals
converters['A:es'] = converters.Spanishnumerals
converters['A:sl'] = converters.Sloveniannumerals
+converters['A:ru'] = converters.Russiannumerals
-- end of bonus
diff --git a/tex/context/base/mkiv/core-con.mkiv b/tex/context/base/mkiv/core-con.mkiv
index 8565a3096..a4d358e04 100644
--- a/tex/context/base/mkiv/core-con.mkiv
+++ b/tex/context/base/mkiv/core-con.mkiv
@@ -739,6 +739,9 @@
\def\spanishnumerals #1{\clf_alphabetic\numexpr#1\relax{es}}
\def\spanishNumerals #1{\clf_Alphabetic\numexpr#1\relax{es}}
+\def\russiannumerals #1{\clf_alphabetic\numexpr#1\relax{ru}}
+\def\russianNumerals #1{\clf_Alphabetic\numexpr#1\relax{ru}}
+
%defineconversion [\s!sl] [character] [\sloveniannumerals]
%defineconversion [\s!sl] [Character] [\slovenianNumerals]
%defineconversion [\s!sl] [characters] [\sloveniannumerals]
@@ -765,12 +768,28 @@
\defineconversion [\s!es] [AK] [\smallcapped\spanishnumerals]
\defineconversion [\s!es] [KA] [\smallcapped\spanishnumerals]
+%defineconversion [\s!ru] [character] [\russiannumerals]
+%defineconversion [\s!ru] [Character] [\russianNumerals]
+%defineconversion [\s!ru] [characters] [\russiannumerals]
+%defineconversion [\s!ru] [Characters] [\russianNumerals]
+
+\defineconversion [\s!ru] [alphabetic] [\russiannumerals]
+\defineconversion [\s!ru] [Alphabetic] [\russianNumerals]
+
+\defineconversion [\s!ru] [a] [\russiannumerals]
+\defineconversion [\s!ru] [A] [\russianNumerals]
+\defineconversion [\s!ru] [AK] [\smallcapped\russiannumerals]
+\defineconversion [\s!ru] [KA] [\smallcapped\russiannumerals]
+
\defineconversion [sloveniannumerals] [\sloveniannumerals]
\defineconversion [slovenianNumerals] [\slovenianNumerals]
\defineconversion [spanishnumerals] [\spanishnumerals]
\defineconversion [spanishNumerals] [\spanishNumerals]
+\defineconversion [russiannumerals] [\russiannumerals]
+\defineconversion [russianNumerals] [\russianNumerals]
+
%D In case a font has no greek (WS):
\defineconversion [mathgreek]
diff --git a/tex/context/base/mkiv/core-ctx.lua b/tex/context/base/mkiv/core-ctx.lua
index 1f22402e6..3362e43b9 100644
--- a/tex/context/base/mkiv/core-ctx.lua
+++ b/tex/context/base/mkiv/core-ctx.lua
@@ -266,7 +266,12 @@ function ctxrunner.load(ctxname)
for i=1,#runners do
local command = runners[i]
report_prepfiles("command: %s",command)
+ --
+ -- remark: we don't use sandbox.registerrunner here as we cannot predict what
+ -- gets done here, so just:
+ --
local result = os.execute(command) or 0
+ --
-- if result > 0 then
-- report_prepfiles("error, return code: %s",result)
-- end
diff --git a/tex/context/base/mkiv/core-uti.lua b/tex/context/base/mkiv/core-uti.lua
index 10f3ffcdc..a2869e6ea 100644
--- a/tex/context/base/mkiv/core-uti.lua
+++ b/tex/context/base/mkiv/core-uti.lua
@@ -418,7 +418,7 @@ function statistics.formatruntime(runtime)
runtime = tonumber(runtime)
local persecond = (runtime > 0) and (shipped/runtime) or pages
if pages == 0 then pages = shipped end
- -- if jit then
+ -- if TEXENGINE == "luajittex" then
-- local saved = watts_per_core * runtime * kg_per_watt_per_second / speedup_by_other_engine
-- local saved = used_wood_factor * runtime
-- return format("%s seconds, %i processed pages, %i shipped pages, %.3f pages/second, %f mg tree saved by using luajittex",runtime,pages,shipped,persecond,saved*1000*1000)
diff --git a/tex/context/base/mkiv/data-crl.lua b/tex/context/base/mkiv/data-crl.lua
index fba5a6230..ec517fba3 100644
--- a/tex/context/base/mkiv/data-crl.lua
+++ b/tex/context/base/mkiv/data-crl.lua
@@ -8,29 +8,45 @@ if not modules then modules = { } end modules ['data-crl'] = {
-- this one is replaced by data-sch.lua --
-local gsub = string.gsub
+local gsub = string.gsub
+local exists = io.exists
local resolvers = resolvers
+local finders = resolvers.finders
+local openers = resolvers.openers
+local loaders = resolvers.loaders
-local finders, openers, loaders = resolvers.finders, resolvers.openers, resolvers.loaders
+local setfirstwritablefile = caches.setfirstwritablefile
-resolvers.curl = resolvers.curl or { }
-local curl = resolvers.curl
+local curl = resolvers.curl or { }
+resolvers.curl = curl
+local cached = { }
-local cached = { }
+local runner = sandbox.registerrunner {
+ name = "curl resolver",
+ method = "execute",
+ program = "curl",
+ template = "--silent -- insecure --create-dirs --output %cachename% %original%",
+ checkers = {
+ cachename = "cache",
+ original = "url",
+ }
+}
local function runcurl(specification)
local original = specification.original
-- local scheme = specification.scheme
local cleanname = gsub(original,"[^%a%d%.]+","-")
- local cachename = caches.setfirstwritablefile(cleanname,"curl")
+ local cachename = setfirstwritablefile(cleanname,"curl")
if not cached[original] then
- if not io.exists(cachename) then
+ if not exists(cachename) then
cached[original] = cachename
- local command = "curl --silent --create-dirs --output " .. cachename .. " " .. original
- os.execute(command)
+ runner {
+ cachename = cachename,
+ original = original,
+ }
end
- if io.exists(cachename) then
+ if exists(cachename) then
cached[original] = cachename
else
cached[original] = ""
diff --git a/tex/context/base/mkiv/data-sch.lua b/tex/context/base/mkiv/data-sch.lua
index d79e0c7ef..23ecdc122 100644
--- a/tex/context/base/mkiv/data-sch.lua
+++ b/tex/context/base/mkiv/data-sch.lua
@@ -61,12 +61,21 @@ function resolvers.schemes.cleanname(specification)
return hash
end
-local cached, loaded, reused, thresholds, handlers = { }, { }, { }, { }, { }
-
-local function runcurl(name,cachename) -- we use sockets instead or the curl library when possible
- local command = "curl --silent --insecure --create-dirs --output " .. cachename .. " " .. name
- os.execute(command)
-end
+local cached = { }
+local loaded = { }
+local reused = { }
+local thresholds = { }
+local handlers = { }
+local runner = sandbox.registerrunner {
+ name = "curl resolver",
+ method = "execute",
+ program = "curl",
+ template = "--silent -- insecure --create-dirs --output %cachename% %original%",
+ checkers = {
+ cachename = "cache",
+ original = "url",
+ }
+}
local function fetch(specification)
local original = specification.original
@@ -89,7 +98,10 @@ local function fetch(specification)
report_schemes("fetching %a, protocol %a, method %a",original,scheme,"curl")
end
logs.flush()
- runcurl(original,cachename)
+ runner {
+ original = original,
+ cachename = cachename,
+ }
end
end
if io.exists(cachename) then
@@ -184,10 +196,6 @@ end)
local httprequest = http.request
local toquery = url.toquery
--- local function httprequest(url)
--- return os.resultof(format("curl --silent %q", url))
--- end
-
local function fetchstring(url,data)
local q = data and toquery(data)
if q then
diff --git a/tex/context/base/mkiv/font-col.lua b/tex/context/base/mkiv/font-col.lua
index b4c16c660..d7b76a615 100644
--- a/tex/context/base/mkiv/font-col.lua
+++ b/tex/context/base/mkiv/font-col.lua
@@ -24,7 +24,7 @@ local getfont = nuts.getfont
local getchar = nuts.getchar
local setfield = nuts.setfield
-local setchar = nuts.setchar
+local setfont = nuts.setfont
local traverse_id = nuts.traverse_id
local traverse_char = nuts.traverse_char
@@ -35,6 +35,9 @@ local trace_collecting = false trackers.register("fonts.collecting", function
local report_fonts = logs.reporter("fonts","collections")
+local enableaction = nodes.tasks.enableaction
+local disableaction = nodes.tasks.disableaction
+
local collections = fonts.collections or { }
fonts.collections = collections
@@ -60,12 +63,12 @@ local function checkenabled()
-- a bit ugly but nicer than a fuzzy state while defining math
if next(vectors) then
if not enabled then
- nodes.tasks.enableaction("processors","fonts.collections.process")
+ enableaction("processors","fonts.collections.process")
enabled = true
end
else
if enabled then
- nodes.tasks.disableaction("processors","fonts.collections.process")
+ disableaction("processors","fonts.collections.process")
enabled = false
end
end
@@ -272,8 +275,7 @@ function collections.process(head) -- this way we keep feature processing
char,font,newchar,newfont,not chardata[newfont][newchar] and " (missing)" or ""
)
end
- setfield(n,"font",newfont)
- setchar(n,newchar)
+ setfont(n,newfont,newchar)
done = true
else
if trace_collecting then
@@ -281,7 +283,7 @@ function collections.process(head) -- this way we keep feature processing
font,vect,char,not chardata[vect][char] and " (missing)" or ""
)
end
- setfield(n,"font",vect)
+ setfont(n,vect)
done = true
end
end
diff --git a/tex/context/base/mkiv/font-ctx.lua b/tex/context/base/mkiv/font-ctx.lua
index 7c986f889..f53a4e643 100644
--- a/tex/context/base/mkiv/font-ctx.lua
+++ b/tex/context/base/mkiv/font-ctx.lua
@@ -961,13 +961,13 @@ local rightparent = (P")")
local value = C((leftparent * (1-rightparent)^0 * rightparent + (1-space))^1)
local dimension = C((space/"" + P(1))^1)
local rest = C(P(1)^0)
-local scale_none = Cc(0)
-local scale_at = P("at") * Cc(1) * spaces * dimension -- dimension
-local scale_sa = P("sa") * Cc(2) * spaces * dimension -- number
-local scale_mo = P("mo") * Cc(3) * spaces * dimension -- number
-local scale_scaled = P("scaled") * Cc(4) * spaces * dimension -- number
-local scale_ht = P("ht") * Cc(5) * spaces * dimension -- dimension
-local scale_cp = P("cp") * Cc(6) * spaces * dimension -- dimension
+local scale_none = Cc(0)
+local scale_at = (P("at") +P("@")) * Cc(1) * spaces * dimension -- dimension
+local scale_sa = P("sa") * Cc(2) * spaces * dimension -- number
+local scale_mo = P("mo") * Cc(3) * spaces * dimension -- number
+local scale_scaled = P("scaled") * Cc(4) * spaces * dimension -- number
+local scale_ht = P("ht") * Cc(5) * spaces * dimension -- dimension
+local scale_cp = P("cp") * Cc(6) * spaces * dimension -- dimension
local specialscale = { [5] = "ht", [6] = "cp" }
diff --git a/tex/context/base/mkiv/font-dsp.lua b/tex/context/base/mkiv/font-dsp.lua
index 14e3a1d62..2d52c23a9 100644
--- a/tex/context/base/mkiv/font-dsp.lua
+++ b/tex/context/base/mkiv/font-dsp.lua
@@ -1699,13 +1699,7 @@ do
rule.lookups = nil
else
-- we can have holes in rlookups
- -- for index, lookupid in sortedhash(rlookups) do
local length = #rlookups
--- for index in next, rlookups do
--- if index > length then
--- length = index
--- end
--- end
for index=1,length do
local lookupid = rlookups[index]
if lookupid then
@@ -1733,6 +1727,7 @@ do
sublookuplist[nofsublookups] = copy(h) -- we repack later
sublookuphash[lookupid] = nofsublookups
sublookupcheck[lookupid] = 1
+ h = nofsublookups
else
report_issue(i,what,sequence,"missing")
rule.lookups = nil
diff --git a/tex/context/base/mkiv/font-hsh.lua b/tex/context/base/mkiv/font-hsh.lua
index efd042fe1..12f7bdfc2 100644
--- a/tex/context/base/mkiv/font-hsh.lua
+++ b/tex/context/base/mkiv/font-hsh.lua
@@ -31,6 +31,7 @@ local xheights = hashes.xheights or allocate()
local csnames = hashes.csnames or allocate() -- namedata
local features = hashes.features or allocate()
local marks = hashes.marks or allocate()
+local classes = hashes.classes or allocate()
local italics = hashes.italics or allocate()
local lastmathids = hashes.lastmathids or allocate()
local dynamics = hashes.dynamics or allocate()
@@ -51,6 +52,7 @@ hashes.xheights = xheights hashes.exheights = xheights
hashes.csnames = csnames
hashes.features = features
hashes.marks = marks
+hashes.classes = classes
hashes.italics = italics
hashes.lastmathids = lastmathids
hashes.dynamics = dynamics
@@ -212,12 +214,23 @@ setmetatableindex(marks, function(t,k)
return marks[currentfont()]
else
local resources = identifiers[k].resources or { }
- local marks = resources.marks or { }
+ local marks = resources.marks or { }
t[k] = marks
return marks
end
end)
+setmetatableindex(classes, function(t,k)
+ if k == true then
+ return classes[currentfont()]
+ else
+ local resources = identifiers[k].resources or { }
+ local classes = resources.classes or { }
+ t[k] = classes
+ return classes
+ end
+end)
+
setmetatableindex(quads, function(t,k)
if k == true then
return quads[currentfont()]
diff --git a/tex/context/base/mkiv/font-inj.lua b/tex/context/base/mkiv/font-inj.lua
index cb4fb7226..ccc41d3f3 100644
--- a/tex/context/base/mkiv/font-inj.lua
+++ b/tex/context/base/mkiv/font-inj.lua
@@ -261,7 +261,7 @@ function injections.setpair(current,factor,rlmode,r2lflag,spec,injection) -- r2l
local i = rawget(p,injection)
if i then
if leftkern ~= 0 then
- i.leftkern = (i.leftkern or 0) + leftkern
+ i.leftkern = (i.leftkern or 0) + leftkern
end
if rightkern ~= 0 then
i.rightkern = (i.rightkern or 0) + rightkern
diff --git a/tex/context/base/mkiv/font-map.lua b/tex/context/base/mkiv/font-map.lua
index e2254f8ca..37a7f03af 100644
--- a/tex/context/base/mkiv/font-map.lua
+++ b/tex/context/base/mkiv/font-map.lua
@@ -186,6 +186,32 @@ local function tounicode(unicode,name)
end
end
+-- no real gain on runs
+--
+-- local hash = setmetatableindex(function(t,u)
+-- local v
+-- if u < 0xD7FF or (u > 0xDFFF and u <= 0xFFFF) then
+-- v = f_single(u)
+-- else
+-- u = u - 0x10000
+-- v = f_double(floor(u/1024)+0xD800,u%1024+0xDC00)
+-- end
+-- t[u] = v
+-- return v
+-- end)
+--
+-- local function tounicode(unicode,name)
+-- if type(unicode) == "table" then
+-- local t = { }
+-- for l=1,#unicode do
+-- t[l] = hash[u]
+-- end
+-- return concat(t)
+-- else
+-- return hash[unicode]
+-- end
+-- end
+
local function fromunicode16(str)
if #str == 4 then
return tonumber(str,16)
diff --git a/tex/context/base/mkiv/font-mps.lua b/tex/context/base/mkiv/font-mps.lua
index 0cda202e6..6c441699b 100644
--- a/tex/context/base/mkiv/font-mps.lua
+++ b/tex/context/base/mkiv/font-mps.lua
@@ -262,6 +262,11 @@ local getsubtype = nuts.getsubtype
local getfield = nuts.getfield
local getbox = nuts.getbox
local getwhd = nuts.getwhd
+local getkern = nuts.getkern
+local getshift = nuts.getshift
+local getwidth = nuts.getwidth
+local getheight = nuts.getheight
+local getdepth = nuts.getdepth
local effective_glue = nuts.effective_glue
@@ -339,30 +344,30 @@ function fonts.metapost.boxtomp(n,kind)
dx = dx + horizontal(parent,replace,xoffset+dx,yoffset)
end
elseif id == kern_code then
- dx = dx + getfield(current,"kern") * fc
+ dx = dx + getkern(current) * fc
elseif id == glue_code then
dx = dx + effective_glue(current,parent) * fc
elseif id == hlist_code then
local list = getlist(current)
if list then
- horizontal(current,list,xoffset+dx,yoffset-getfield(current,"shift")*fc)
+ horizontal(current,list,xoffset+dx,yoffset-getshift(current)*fc)
end
- dx = dx + getfield(current,"width") * fc
+ dx = dx + getwidth(current) * fc
elseif id == vlist_code then
local list = getlist(current)
if list then
- vertical(current,list,xoffset+dx,yoffset-getfield(current,"shift")*fc)
+ vertical(current,list,xoffset+dx,yoffset-getshift(current)*fc)
end
- dx = dx + getfield(current,"width") * fc
+ dx = dx + getwidth(current) * fc
elseif id == rule_code then
local wd, ht, dp = getwhd(current)
if wd ~= 0 then
wd = wd * fc
if ht == signal then
- ht = getfield(parent,"height")
+ ht = getheight(parent)
end
if dp == signal then
- dp = getfield(parent,"depth")
+ dp = getdepth(parent)
end
local hd = (ht + dp) * fc
if hd ~= 0 and getsubtype(current) == normal_rule then
@@ -377,7 +382,7 @@ function fonts.metapost.boxtomp(n,kind)
end
vertical = function(parent,current,xoffset,yoffset)
- local dy = getfield(parent,"height") * fc
+ local dy = getheight(parent) * fc
while current do
local id = getid(current)
if id == hlist_code then
@@ -385,18 +390,19 @@ function fonts.metapost.boxtomp(n,kind)
dy = dy - ht * fc
local list = getlist(current)
if list then
- horizontal(current,list,xoffset+getfield(current,"shift")*fc,yoffset+dy)
+ horizontal(current,list,xoffset+getshift(current)*fc,yoffset+dy)
end
- dy = dy - ht * fc
+ dy = dy - dp * fc
elseif id == vlist_code then
- dy = dy - getfield(current,"height") * fc
+ local wd, ht, dp = getwhd(current)
+ dy = dy - ht * fc
local list = getlist(current)
if list then
- vertical(current,list,xoffset+getfield(current,"shift")*fc,yoffset+dy)
+ vertical(current,list,xoffset+getshift(current)*fc,yoffset+dy)
end
- dy = dy - getfield(current,"depth") * fc
+ dy = dy - dp * fc
elseif id == kern_code then
- dy = dy - getfield(current,"kern") * fc
+ dy = dy - getkern(current) * fc
elseif id == glue_code then
dy = dy - effective_glue(current,parent) * fc
elseif id == rule_code then
@@ -404,7 +410,7 @@ function fonts.metapost.boxtomp(n,kind)
local hd = (ht + dp) * fc
if hd ~= 0 then
if wd == signal then
- wd = getfield(parent,"width") * fc
+ wd = getwidth(parent) * fc
else
wd = wd * fc
end
diff --git a/tex/context/base/mkiv/font-nod.lua b/tex/context/base/mkiv/font-nod.lua
index 41fc215b1..2b70ee104 100644
--- a/tex/context/base/mkiv/font-nod.lua
+++ b/tex/context/base/mkiv/font-nod.lua
@@ -63,7 +63,11 @@ local getsubtype = nuts.getsubtype
local getchar = nuts.getchar
local getlist = nuts.getlist
local getdisc = nuts.getdisc
+local getcomponents = nuts.getcomponents
local isglyph = nuts.isglyph
+local getkern = nuts.getkern
+local getdir = nuts.getdir
+local getwidth = nuts.getwidth
local setfield = nuts.setfield
local setbox = nuts.setbox
@@ -388,7 +392,7 @@ function step_tracers.codes(i,command,space)
if id == glyph_code then
showchar(c)
elseif id == dir_code or id == localpar_code then
- context("[%s]",getfield(c,"dir"))
+ context("[%s]",getdir(c))
elseif id == disc_code then
local pre, post, replace = getdisc(c)
if pre or post or replace then
@@ -476,7 +480,7 @@ local function toutf(list,result,nofresult,stopcriterium,nostrip)
for n in traverse_nodes(tonut(list)) do
local c, id = isglyph(n)
if c then
- local components = getfield(n,"components")
+ local components = getcomponents(n)
if components then
result, nofresult = toutf(components,result,nofresult,false,true)
elseif c > 0 then
@@ -518,12 +522,12 @@ local function toutf(list,result,nofresult,stopcriterium,nostrip)
-- end
result, nofresult = toutf(getlist(n),result,nofresult,false,true)
elseif id == glue_code then
- if nofresult > 0 and result[nofresult] ~= " " and getfield(n,"width") > threshold then
+ if nofresult > 0 and result[nofresult] ~= " " and getwidth(n) > threshold then
nofresult = nofresult + 1
result[nofresult] = " "
end
elseif id == kern_code then
- if nofresult > 0 and result[nofresult] ~= " " and getfield(n,"kern") > threshold then
+ if nofresult > 0 and result[nofresult] ~= " " and getkern(n) > threshold then
nofresult = nofresult + 1
result[nofresult] = " "
end
diff --git a/tex/context/base/mkiv/font-ocl.lua b/tex/context/base/mkiv/font-ocl.lua
index 65a1c6342..824f09125 100644
--- a/tex/context/base/mkiv/font-ocl.lua
+++ b/tex/context/base/mkiv/font-ocl.lua
@@ -261,77 +261,66 @@ do
end
- -- function otfsvg.topdf(svgshapes)
- -- local svgfile = "temp-otf-svg-shape.svg"
- -- local pdffile = "temp-otf-svg-shape.pdf"
- -- local command = "inkscape " .. svgfile .. " --export-pdf=" .. pdffile
- -- local testrun = false
- -- local pdfshapes = { }
- -- local nofshapes = #svgshapes
- -- local filterglyph = otfsvg.filterglyph
- -- report_svg("processing %i svg containers",nofshapes)
- -- statistics.starttiming()
- -- for i=1,nofshapes do
- -- local entry = svgshapes[i]
- -- for index=entry.first,entry.last do
- -- local data = filterglyph(entry,index)
- -- savedata(svgfile,tostring(data))
- -- if data and data ~= "" then
- -- report_svg("processing svg shape of glyph %i in container %i",index,i)
- -- os.execute(command)
- -- pdfshapes[index] = loaddata(pdffile)
- -- end
- -- end
- -- if testrun and i > testrun then
- -- report_svg("quiting test run")
- -- break
- -- end
- -- end
- -- remove(svgfile)
- -- statistics.stoptiming()
- -- report_svg("conversion time: %0.3f",statistics.elapsedtime())
- -- return pdfshapes
- -- end
+ local runner = sandbox and sandbox.registerrunner {
+ name = "otfsvg",
+ program = "inkscape",
+ method = "pipeto",
+ template = "--shell > temp-otf-svg-shape.log",
+ reporter = report_svg,
+ }
+
+ if notrunner then
+ --
+ -- poor mans variant for generic:
+ --
+ runner = function()
+ return io.open("inkscape --shell > temp-otf-svg-shape.log","w")
+ end
+ end
function otfsvg.topdf(svgshapes)
- local inkscape = io.popen("inkscape --shell > temp-otf-svg-shape.log","w")
- local pdfshapes = { }
- local nofshapes = #svgshapes
- local f_svgfile = formatters["temp-otf-svg-shape-%i.svg"]
- local f_pdffile = formatters["temp-otf-svg-shape-%i.pdf"]
- local f_convert = formatters["%s --export-pdf=%s\n"]
- local filterglyph = otfsvg.filterglyph
- report_svg("processing %i svg containers",nofshapes)
- statistics.starttiming()
- for i=1,nofshapes do
- local entry = svgshapes[i]
- for index=entry.first,entry.last do
- local data = filterglyph(entry,index)
- if data and data ~= "" then
- local svgfile = f_svgfile(index)
- local pdffile = f_pdffile(index)
- savedata(svgfile,data)
- inkscape:write(f_convert(svgfile,pdffile))
- pdfshapes[index] = true
+ local pdfshapes = { }
+ local inkscape = runner()
+ if inkscape then
+ local nofshapes = #svgshapes
+ local f_svgfile = formatters["temp-otf-svg-shape-%i.svg"]
+ local f_pdffile = formatters["temp-otf-svg-shape-%i.pdf"]
+ local f_convert = formatters["%s --export-pdf=%s\n"]
+ local filterglyph = otfsvg.filterglyph
+ local nofdone = 0
+ report_svg("processing %i svg containers",nofshapes)
+ statistics.starttiming()
+ for i=1,nofshapes do
+ local entry = svgshapes[i]
+ for index=entry.first,entry.last do
+ local data = filterglyph(entry,index)
+ if data and data ~= "" then
+ local svgfile = f_svgfile(index)
+ local pdffile = f_pdffile(index)
+ savedata(svgfile,data)
+ inkscape:write(f_convert(svgfile,pdffile))
+ pdfshapes[index] = true
+ nofdone = nofdone + 1
+ if nofdone % 100 == 0 then
+ report_svg("%i shapes processed",nofdone)
+ end
+ end
end
end
- end
- inkscape:write("quit\n")
- -- while inkscape:read("*a") do
- -- os.sleep(0.1)
- -- end
- inkscape:close()
- report_svg("processing %i pdf results",nofshapes)
- for index in next, pdfshapes do
- local svgfile = f_svgfile(index)
- local pdffile = f_pdffile(index)
- pdfshapes[index] = loaddata(pdffile)
- remove(svgfile)
- remove(pdffile)
- end
- statistics.stoptiming()
- if statistics.elapsedseconds then
- report_svg("svg conversion time %s",statistics.elapsedseconds())
+ inkscape:write("quit\n")
+ inkscape:close()
+ report_svg("processing %i pdf results",nofshapes)
+ for index in next, pdfshapes do
+ local svgfile = f_svgfile(index)
+ local pdffile = f_pdffile(index)
+ pdfshapes[index] = loaddata(pdffile)
+ remove(svgfile)
+ remove(pdffile)
+ end
+ statistics.stoptiming()
+ if statistics.elapsedseconds then
+ report_svg("svg conversion time %s",statistics.elapsedseconds())
+ end
end
return pdfshapes
end
diff --git a/tex/context/base/mkiv/font-osd.lua b/tex/context/base/mkiv/font-osd.lua
index b67cc9241..ca20f6782 100644
--- a/tex/context/base/mkiv/font-osd.lua
+++ b/tex/context/base/mkiv/font-osd.lua
@@ -1140,6 +1140,7 @@ function handlers.devanagari_reorder_matras(head,start) -- no leak
head = remove_node(head,start)
setlink(start,next)
setlink(current,start)
+ -- setlink(current,start,next) -- maybe
start = startnext
break
end
@@ -1199,6 +1200,7 @@ function handlers.devanagari_reorder_reph(head,start)
head = remove_node(head,start)
setlink(start,next)
setlink(current,start)
+ -- setlink(current,start,next) -- maybe
start = startnext
startattr = getprop(start,a_syllabe)
break
@@ -1216,9 +1218,9 @@ function handlers.devanagari_reorder_reph(head,start)
if getprop(current,a_state) == s_pstf then -- post-base
startnext = getnext(start)
head = remove_node(head,start)
- local prev = getprev(current)
- setlink(prev,start)
+ setlink(getprev(current),start)
setlink(start,current)
+ -- setlink(getprev(current),start,current) -- maybe
start = startnext
startattr = getprop(start,a_syllabe)
break
@@ -1250,9 +1252,9 @@ function handlers.devanagari_reorder_reph(head,start)
if c then
startnext = getnext(start)
head = remove_node(head,start)
- local prev = getprev(c)
- setlink(prev,start)
+ setlink(getprev(c),start)
setlink(start,c)
+ -- setlink(getprev(c),start,c) -- maybe
-- end
start = startnext
startattr = getprop(start,a_syllabe)
@@ -1274,9 +1276,9 @@ function handlers.devanagari_reorder_reph(head,start)
if start ~= current then
startnext = getnext(start)
head = remove_node(head,start)
- local next = getnext(current)
- setlink(start,next)
+ setlink(start,getnext(current))
setlink(current,start)
+ -- setlink(current,start,getnext(current)) -- maybe
start = startnext
end
end
@@ -1320,6 +1322,7 @@ function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start)
removenode(start,start)
setlink(start,next)
setlink(current,start)
+ -- setlink(current,start,next) -- maybe
start = startnext
break
end
@@ -1337,9 +1340,9 @@ function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start)
if not consonant[char] and getprop(current,a_state) then -- main
startnext = getnext(start)
removenode(start,start)
- local prev = getprev(current)
- setlink(prev,start)
+ setlink(getprev(current),start)
setlink(start,current)
+ -- setlink(getprev(current),start,current) -- maybe
start = startnext
break
end
@@ -1690,9 +1693,9 @@ local function dev2_reorder(head,start,stop,font,attr,nbspaces) -- maybe do a pa
end
start = current
end
- local prev = getprev(halfpos)
- setlink(prev,current)
+ setlink(getprev(halfpos),current)
setlink(current,halfpos)
+ -- setlink(getprev(halfpos),current,halfpos) -- maybe
halfpos = current
elseif above_mark[char] then -- After main consonant
target = basepos
@@ -1721,9 +1724,9 @@ local function dev2_reorder(head,start,stop,font,attr,nbspaces) -- maybe do a pa
if current == stop then
stop = prev
end
- local next = getnext(target)
- setlink(current,next)
+ setlink(current,getnext(target))
setlink(target,current)
+ -- setlink(target,current,getnext(target)) -- maybe
end
end
end
@@ -1750,8 +1753,7 @@ local function dev2_reorder(head,start,stop,font,attr,nbspaces) -- maybe do a pa
if stop == next then
stop = current
end
- local prev = getprev(c)
- setlink(prev,next)
+ setlink(getprev(c),next)
local nextnext = getnext(next)
setnext(current,nextnext)
local nextnextnext = getnext(nextnext)
diff --git a/tex/context/base/mkiv/font-ota.lua b/tex/context/base/mkiv/font-ota.lua
index b8944e0c0..232c2586a 100644
--- a/tex/context/base/mkiv/font-ota.lua
+++ b/tex/context/base/mkiv/font-ota.lua
@@ -32,7 +32,6 @@ local a_state = attributes.private('state')
local nuts = nodes.nuts
local tonut = nuts.tonut
-local getfield = nuts.getfield
local getnext = nuts.getnext
local getprev = nuts.getprev
local getprev = nuts.getprev
diff --git a/tex/context/base/mkiv/font-otf.lua b/tex/context/base/mkiv/font-otf.lua
index 09e810857..1db80272e 100644
--- a/tex/context/base/mkiv/font-otf.lua
+++ b/tex/context/base/mkiv/font-otf.lua
@@ -24,7 +24,6 @@ local gmatch, gsub, find, match, lower, strip = string.gmatch, string.gsub, stri
local type, next, tonumber, tostring = type, next, tonumber, tostring
local abs = math.abs
local reversed, concat, insert, remove, sortedkeys = table.reversed, table.concat, table.insert, table.remove, table.sortedkeys
-local ioflush = io.flush
local fastcopy, tohash, derivetable, copy = table.fastcopy, table.tohash, table.derive, table.copy
local formatters = string.formatters
local P, R, S, C, Ct, lpegmatch = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Ct, lpeg.match
diff --git a/tex/context/base/mkiv/font-otj.lua b/tex/context/base/mkiv/font-otj.lua
index 68cf608ec..fdee3513f 100644
--- a/tex/context/base/mkiv/font-otj.lua
+++ b/tex/context/base/mkiv/font-otj.lua
@@ -16,12 +16,9 @@ if not modules then modules = { } end modules ['font-otj'] = {
-- cleaner to have an identification pass here. Also, I need to keep tracing in mind so
-- being too clever here is dangerous.
--- The subtype test is not needed as there will be no (new) properties set, given that we
--- reset the properties.
-
-- As we have a rawget on properties we don't need one on injections.
--- The use_advance code is just a test and is meant for testing and manuals. There is no
+-- The use_advance code was just a test and is meant for testing and manuals. There is no
-- performance (or whatever) gain and using kerns is somewhat cleaner (at least for now).
-- Maybe: subtype fontkern when pure kerns.
@@ -38,10 +35,6 @@ local trace_marks = false registertracker("fonts.injections.marks", fun
local trace_cursive = false registertracker("fonts.injections.cursive", function(v) trace_cursive = v end)
local trace_spaces = false registertracker("fonts.injections.spaces", function(v) trace_spaces = v end)
--- use_advance is just an experiment: it makes copying glyphs (instead of new_glyph) dangerous
-
-local use_advance = false directives.register("fonts.injections.advance", function(v) use_advance = v end)
-
local report_injections = logs.reporter("fonts","injections")
local report_spaces = logs.reporter("fonts","spaces")
@@ -80,14 +73,18 @@ local getnext = nuts.getnext
local getprev = nuts.getprev
local getid = nuts.getid
local getfont = nuts.getfont
-local getsubtype = nuts.getsubtype
local getchar = nuts.getchar
+local getoffsets = nuts.getoffsets
local getboth = nuts.getboth
-
-local ischar = nuts.is_char
-
local getdisc = nuts.getdisc
local setdisc = nuts.setdisc
+local setoffsets = nuts.setoffsets
+local ischar = nuts.is_char
+local getkern = nuts.getkern
+local setkern = nuts.setkern
+local setlink = nuts.setlink
+local setwidth = nuts.setwidth
+local getwidth = nuts.getwidth
local traverse_id = nuts.traverse_id
local traverse_char = nuts.traverse_char
@@ -137,7 +134,7 @@ end
-- if tp then
-- tp.injections = si
-- else
--- propertydata[target] = {
+-- properties[target] = {
-- injections = si,
-- }
-- end
@@ -169,7 +166,7 @@ function injections.copy(target,source)
if tp then
tp.injections = si
else
- propertydata[target] = {
+ properties[target] = {
injections = si,
}
end
@@ -527,11 +524,12 @@ local function show_result(head)
while current do
local id = getid(current)
if id == glyph_code then
- report_injections("char: %C, width %p, xoffset %p, yoffset %p",
- getchar(current),getfield(current,"width"),getfield(current,"xoffset"),getfield(current,"yoffset"))
+ local w = getwidth(current)
+ local x, y = getoffsets(current)
+ report_injections("char: %C, width %p, xoffset %p, yoffset %p",getchar(current),w,x,y)
skipping = false
elseif id == kern_code then
- report_injections("kern: %p",getfield(current,"kern"))
+ report_injections("kern: %p",getkern(current))
skipping = false
elseif not skipping then
report_injections()
@@ -566,76 +564,65 @@ local function inject_kerns_only(head,where)
local posttail = nil -- saves a lookup
local replacetail = nil -- saves a lookup
while current do
- local id = getid(current)
local next = getnext(current)
- if id == glyph_code then
- if getsubtype(current) < 256 then
- local p = rawget(properties,current)
- if p then
- -- local i = rawget(p,"injections")
- local i = p.injections
- if i then
- -- left|glyph|right
- local leftkern = i.leftkern
- if leftkern and leftkern ~= 0 then
- if use_advance then
- setfield(current,"xoffset",leftkern)
- setfield(current,"xadvance",leftkern)
- else
- insert_node_before(head,current,newkern(leftkern))
+ local char, id = ischar(current)
+ if char then
+ local p = rawget(properties,current)
+ if p then
+ -- local i = rawget(p,"injections")
+ local i = p.injections
+ if i then
+ -- left|glyph|right
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ insert_node_before(head,current,newkern(leftkern))
+ end
+ end
+ if prevdisc then
+ local done = false
+ if post then
+ -- local i = rawget(p,"postinjections")
+ local i = p.postinjections
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ setlink(posttail,newkern(leftkern))
+ done = true
end
end
end
- if prevdisc then
- local done = false
- if post then
- -- local i = rawget(p,"postinjections")
- local i = p.postinjections
- if i then
- local leftkern = i.leftkern
- if leftkern and leftkern ~= 0 then
- if use_advance then
- setfield(post,"xadvance",leftkern)
- else
- insert_node_after(post,posttail,newkern(leftkern))
- done = true
- end
- end
+ if replace then
+ -- local i = rawget(p,"replaceinjections")
+ local i = p.replaceinjections
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ setlink(replacetail,newkern(leftkern))
+ done = true
end
end
- if replace then
- -- local i = rawget(p,"replaceinjections")
- local i = p.replaceinjections
- if i then
- local leftkern = i.leftkern
- if leftkern and leftkern ~= 0 then
- if use_advance then
- setfield(replace,"xadvance",leftkern)
- else
- insert_node_after(replace,replacetail,newkern(leftkern))
- done = true
- end
- end
- end
- else
- -- local i = rawget(p,"emptyinjections")
- local i = p.emptyinjections
- if i then
- -- glyph|disc|glyph (special case)
- local leftkern = i.leftkern
- if leftkern and leftkern ~= 0 then
- setfield(prev,"replace",newkern(leftkern)) -- maybe also leftkern
- end
+ else
+ -- local i = rawget(p,"emptyinjections")
+ local i = p.emptyinjections
+ if i then
+ -- glyph|disc|glyph (special case)
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ setfield(prev,"replace",newkern(leftkern)) -- maybe also leftkern
end
end
- if done then
- setdisc(prevdisc,pre,post,replace)
- end
+ end
+ if done then
+ setdisc(prevdisc,pre,post,replace)
end
end
end
prevdisc = nil
prevglyph = current
+ elseif char == false then
+ -- other font
+ prevdisc = nil
+ prevglyph = current
elseif id == disc_code then
pre, post, replace, pretail, posttail, replacetail = getdisc(current,true)
local done = false
@@ -649,13 +636,8 @@ local function inject_kerns_only(head,where)
if i then
local leftkern = i.leftkern
if leftkern and leftkern ~= 0 then
- if use_advance then
- setfield(pre,"xoffset",leftkern)
- setfield(pre,"xadvance",leftkern)
- else
- pre = insert_node_before(pre,n,newkern(leftkern))
- done = true
- end
+ pre = insert_node_before(pre,n,newkern(leftkern))
+ done = true
end
end
end
@@ -671,13 +653,8 @@ local function inject_kerns_only(head,where)
if i then
local leftkern = i.leftkern
if leftkern and leftkern ~= 0 then
- if use_advance then
- setfield(post,"xoffset",leftkern)
- setfield(post,"xadvance",leftkern)
- else
- post = insert_node_before(post,n,newkern(leftkern))
- done = true
- end
+ post = insert_node_before(post,n,newkern(leftkern))
+ done = true
end
end
end
@@ -693,13 +670,8 @@ local function inject_kerns_only(head,where)
if i then
local leftkern = i.leftkern
if leftkern and leftkern ~= 0 then
- if use_advance then
- setfield(replace,"xoffset",leftkern)
- setfield(replace,"xadvance",leftkern)
- else
- replace = insert_node_before(replace,n,newkern(leftkern))
- done = true
- end
+ replace = insert_node_before(replace,n,newkern(leftkern))
+ done = true
end
end
end
@@ -743,87 +715,88 @@ local function inject_pairs_only(head,where)
local posttail = nil -- saves a lookup
local replacetail = nil -- saves a lookup
while current do
- local id = getid(current)
local next = getnext(current)
- if id == glyph_code then
- if getsubtype(current) < 256 then
- local p = rawget(properties,current)
- if p then
- -- local i = rawget(p,"injections")
- local i = p.injections
+ local char, id = ischar(current)
+ if char then
+ local p = rawget(properties,current)
+ if p then
+ -- local i = rawget(p,"injections")
+ local i = p.injections
+ if i then
+ -- left|glyph|right
+ local yoffset = i.yoffset
+ if yoffset and yoffset ~= 0 then
+ setoffsets(current,false,yoffset)
+ end
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ head = insert_node_before(head,current,newkern(leftkern))
+ end
+ local rightkern = i.rightkern
+ if rightkern and rightkern ~= 0 then
+ insert_node_after(head,current,newkern(rightkern))
+ end
+ else
+ -- local i = rawget(p,"emptyinjections")
+ local i = p.emptyinjections
if i then
- -- left|glyph|right
- local yoffset = i.yoffset
- if yoffset and yoffset ~= 0 then
- setfield(current,"yoffset",yoffset)
- end
- local leftkern = i.leftkern
- if leftkern and leftkern ~= 0 then
- head = insert_node_before(head,current,newkern(leftkern))
- end
+ -- glyph|disc|glyph (special case)
+-- is this okay?
local rightkern = i.rightkern
if rightkern and rightkern ~= 0 then
- insert_node_after(head,current,newkern(rightkern))
- end
- else
- -- local i = rawget(p,"emptyinjections")
- local i = p.emptyinjections
- if i then
- -- glyph|disc|glyph (special case)
--- is this okay?
- local rightkern = i.rightkern
- if rightkern and rightkern ~= 0 then
- if next and getid(next) == disc_code then
- if replace then
- -- error, we expect an empty one
- else
- setfield(next,"replace",newkern(rightkern)) -- maybe also leftkern
- end
+ if next and getid(next) == disc_code then
+ if replace then
+ -- error, we expect an empty one
+ else
+ setfield(next,"replace",newkern(rightkern)) -- maybe also leftkern
end
end
end
end
- if prevdisc then
- local done = false
- if post then
- -- local i = rawget(p,"postinjections")
- local i = p.postinjections
- if i then
- local leftkern = i.leftkern
- if leftkern and leftkern ~= 0 then
- insert_node_after(post,posttail,newkern(leftkern))
- done = true
- end
+ end
+ if prevdisc then
+ local done = false
+ if post then
+ -- local i = rawget(p,"postinjections")
+ local i = p.postinjections
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ setlink(posttail,newkern(leftkern))
+ done = true
end
end
- if replace then
- -- local i = rawget(p,"replaceinjections")
- local i = p.replaceinjections
- if i then
- local leftkern = i.leftkern
- if leftkern and leftkern ~= 0 then
- insert_node_after(replace,replacetail,newkern(leftkern))
- done = true
- end
- end
- else
- local i = p.emptyinjections
- if i then
--- new .. okay?
- local leftkern = i.leftkern
- if leftkern and leftkern ~= 0 then
- setfield(prev,"replace",newkern(leftkern)) -- maybe also leftkern
- end
+ end
+ if replace then
+ -- local i = rawget(p,"replaceinjections")
+ local i = p.replaceinjections
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ setlink(replacetail,newkern(leftkern))
+ done = true
end
end
- if done then
- setdisc(prevdisc,pre,post,replace)
+ else
+ local i = p.emptyinjections
+ if i then
+ -- new .. okay?
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ setfield(prev,"replace",newkern(leftkern)) -- maybe also leftkern
+ end
end
end
+ if done then
+ setdisc(prevdisc,pre,post,replace)
+ end
end
end
prevdisc = nil
prevglyph = current
+ elseif char == false then
+ prevdisc = nil
+ prevglyph = current
elseif id == disc_code then
pre, post, replace, pretail, posttail, replacetail = getdisc(current,true)
local done = false
@@ -837,7 +810,7 @@ local function inject_pairs_only(head,where)
if i then
local yoffset = i.yoffset
if yoffset and yoffset ~= 0 then
- setfield(n,"yoffset",yoffset)
+ setoffsets(n,false,yoffset)
end
local leftkern = i.leftkern
if leftkern and leftkern ~= 0 then
@@ -863,7 +836,7 @@ local function inject_pairs_only(head,where)
if i then
local yoffset = i.yoffset
if yoffset and yoffset ~= 0 then
- setfield(n,"yoffset",yoffset)
+ setoffsets(n,false,yoffset)
end
local leftkern = i.leftkern
if leftkern and leftkern ~= 0 then
@@ -889,7 +862,7 @@ local function inject_pairs_only(head,where)
if i then
local yoffset = i.yoffset
if yoffset and yoffset ~= 0 then
- setfield(n,"yoffset",yoffset)
+ setoffsets(n,false,yoffset)
end
local leftkern = i.leftkern
if leftkern and leftkern ~= 0 then
@@ -958,30 +931,9 @@ local function inject_pairs_only(head,where)
return tonode(head), true
end
--- local function showoffset(n,flag)
--- local ox = getfield(n,"xoffset")
--- local oy = getfield(n,"yoffset")
--- if flag then
--- if ox == 0 then
--- setcolor(n,oy == 0 and "darkgray" or "darkgreen")
--- else
--- setcolor(n,oy == 0 and "darkblue" or "darkred")
--- end
--- else
--- if ox == 0 then
--- setcolor(n,oy == 0 and "gray" or "green")
--- else
--- setcolor(n,oy == 0 and "blue" or "red")
--- end
--- end
--- end
-
local function showoffset(n,flag)
- local o = getfield(n,"xoffset")
- if o == 0 then
- o = getfield(n,"yoffset")
- end
- if o ~= 0 then
+ local x, y = getoffsets(n)
+ if x ~= 0 or y ~= 0 then
setcolor(n,flag and "darkred" or "darkgreen")
else
resetcolor(n)
@@ -1021,7 +973,8 @@ local function inject_everything(head,where)
-- move out
--
local function processmark(p,n,pn) -- p = basenode
- local px = getfield(p,"xoffset")
+ local px, py = getoffsets(p)
+ local nx, ny = getoffsets(n)
local ox = 0
local rightkern = nil
local pp = rawget(properties,p)
@@ -1039,7 +992,7 @@ local function inject_everything(head,where)
-- report_injections("r2l case 1: %p",ox)
else
-- kern(x) glyph(p) kern(w-x) mark(n)
- -- ox = px - getfield(p,"width") + pn.markx - pp.leftkern
+ -- ox = px - getwidth(p) + pn.markx - pp.leftkern
--
-- According to Kai we don't need to handle leftkern here but I'm
-- pretty sure I've run into a case where it was needed so maybe
@@ -1062,12 +1015,12 @@ local function inject_everything(head,where)
-- ox = px - pn.markx
-- -- report_injections("r2l case 3: %p",ox)
-- else
- -- -- ox = px - getfield(p,"width") + pn.markx
+ -- -- ox = px - getwidth(p) + pn.markx
ox = px - pn.markx
-- report_injections("l2r case 3: %p",ox)
-- end
if pn.checkmark then
- local wn = getfield(n,"width") -- in arial marks have widths
+ local wn = getwidth(n) -- in arial marks have widths
if wn ~= 0 then
wn = wn/2
if trace_injections then
@@ -1084,167 +1037,168 @@ local function inject_everything(head,where)
end
end
end
- local oy = getfield(n,"yoffset") + getfield(p,"yoffset") + pn.marky
- setfield(n,"xoffset",ox)
- setfield(n,"yoffset",oy)
+ local oy = ny + py + pn.marky
+ setoffsets(n,ox,oy)
if trace_marks then
showoffset(n,true)
end
end
-- todo: marks in disc
while current do
- local id = getid(current)
local next = getnext(current)
- if id == glyph_code then
- if getsubtype(current) < 256 then
- local p = rawget(properties,current)
- if p then
- -- local i = rawget(p,"injections")
- local i = p.injections
- if i then
- local pm = i.markbasenode
- if pm then
- nofmarks = nofmarks + 1
- marks[nofmarks] = current
- else
- local yoffset = i.yoffset
- if yoffset and yoffset ~= 0 then
- setfield(current,"yoffset",yoffset)
- end
- if hascursives then
- local cursivex = i.cursivex
- if cursivex then
- if cursiveanchor then
- if cursivex ~= 0 then
- i.leftkern = (i.leftkern or 0) + cursivex
- end
- if maxc == 0 then
- minc = 1
- maxc = 1
- glyphs[1] = cursiveanchor
- else
- maxc = maxc + 1
- glyphs[maxc] = cursiveanchor
- end
- properties[cursiveanchor].cursivedy = i.cursivey -- cursiveprops
- last = current
+ local char, id = ischar(current)
+ if char then
+ local p = rawget(properties,current)
+ if p then
+ -- local i = rawget(p,"injections")
+ local i = p.injections
+ if i then
+ local pm = i.markbasenode
+ if pm then
+ nofmarks = nofmarks + 1
+ marks[nofmarks] = current
+ else
+ local yoffset = i.yoffset
+ if yoffset and yoffset ~= 0 then
+ setoffsets(current,false,yoffset)
+ end
+ if hascursives then
+ local cursivex = i.cursivex
+ if cursivex then
+ if cursiveanchor then
+ if cursivex ~= 0 then
+ i.leftkern = (i.leftkern or 0) + cursivex
+ end
+ if maxc == 0 then
+ minc = 1
+ maxc = 1
+ glyphs[1] = cursiveanchor
else
- maxc = 0
+ maxc = maxc + 1
+ glyphs[maxc] = cursiveanchor
+ end
+ properties[cursiveanchor].cursivedy = i.cursivey -- cursiveprops
+ last = current
+ else
+ maxc = 0
+ end
+ elseif maxc > 0 then
+ local nx, ny = getoffsets(current)
+ for i=maxc,minc,-1 do
+ local ti = glyphs[i]
+ ny = ny + properties[ti].cursivedy
+ setoffsets(ti,false,ny) -- why not add ?
+ if trace_cursive then
+ showoffset(ti)
end
- elseif maxc > 0 then
- local ny = getfield(current,"yoffset")
+ end
+ maxc = 0
+ cursiveanchor = nil
+ end
+ if i.cursiveanchor then
+ cursiveanchor = current -- no need for both now
+ else
+ if maxc > 0 then
+ local nx, ny = getoffsets(current)
for i=maxc,minc,-1 do
local ti = glyphs[i]
ny = ny + properties[ti].cursivedy
- setfield(ti,"yoffset",ny) -- why not add ?
+ setoffsets(ti,false,ny) -- why not add ?
if trace_cursive then
showoffset(ti)
end
end
maxc = 0
- cursiveanchor = nil
- end
- if i.cursiveanchor then
- cursiveanchor = current -- no need for both now
- else
- if maxc > 0 then
- local ny = getfield(current,"yoffset")
- for i=maxc,minc,-1 do
- local ti = glyphs[i]
- ny = ny + properties[ti].cursivedy
- setfield(ti,"yoffset",ny) -- why not add ?
- if trace_cursive then
- showoffset(ti)
- end
- end
- maxc = 0
- end
- cursiveanchor = nil
end
- end
- -- left|glyph|right
- local leftkern = i.leftkern
- if leftkern and leftkern ~= 0 then
- insert_node_before(head,current,newkern(leftkern))
- end
- local rightkern = i.rightkern
- if rightkern and rightkern ~= 0 then
- insert_node_after(head,current,newkern(rightkern))
+ cursiveanchor = nil
end
end
- else
- -- local i = rawget(p,"emptyinjections")
- local i = p.emptyinjections
- if i then
- -- glyph|disc|glyph (special case)
- -- okay?
- local rightkern = i.rightkern
- if rightkern and rightkern ~= 0 then
- if next and getid(next) == disc_code then
- if replace then
- -- error, we expect an empty one
- else
- setfield(next,"replace",newkern(rightkern)) -- maybe also leftkern
- end
+ -- left|glyph|right
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ insert_node_before(head,current,newkern(leftkern))
+ end
+ local rightkern = i.rightkern
+ if rightkern and rightkern ~= 0 then
+ insert_node_after(head,current,newkern(rightkern))
+ end
+ end
+ else
+ -- local i = rawget(p,"emptyinjections")
+ local i = p.emptyinjections
+ if i then
+ -- glyph|disc|glyph (special case)
+ -- okay?
+ local rightkern = i.rightkern
+ if rightkern and rightkern ~= 0 then
+ if next and getid(next) == disc_code then
+ if replace then
+ -- error, we expect an empty one
+ else
+ setfield(next,"replace",newkern(rightkern)) -- maybe also leftkern
end
end
end
end
- if prevdisc then
- if p then
- local done = false
- if post then
- -- local i = rawget(p,"postinjections")
- local i = p.postinjections
- if i then
- local leftkern = i.leftkern
- if leftkern and leftkern ~= 0 then
- insert_node_after(post,posttail,newkern(leftkern))
- done = true
- end
+ end
+ if prevdisc then
+ if p then
+ local done = false
+ if post then
+ -- local i = rawget(p,"postinjections")
+ local i = p.postinjections
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ setlink(posttail,newkern(leftkern))
+ done = true
end
end
- if replace then
- -- local i = rawget(p,"replaceinjections")
- local i = p.replaceinjections
- if i then
- local leftkern = i.leftkern
- if leftkern and leftkern ~= 0 then
- insert_node_after(replace,replacetail,newkern(leftkern))
- done = true
- end
- end
- else
- -- local i = rawget(p,"emptyinjections")
- local i = p.emptyinjections
- if i then
- local leftkern = i.leftkern
- if leftkern and leftkern ~= 0 then
- setfield(prev,"replace",newkern(leftkern)) -- maybe also leftkern
- end
+ end
+ if replace then
+ -- local i = rawget(p,"replaceinjections")
+ local i = p.replaceinjections
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ setlink(replacetail,newkern(leftkern))
+ done = true
end
end
- if done then
- setdisc(prevdisc,pre,post,replace)
+ else
+ -- local i = rawget(p,"emptyinjections")
+ local i = p.emptyinjections
+ if i then
+ local leftkern = i.leftkern
+ if leftkern and leftkern ~= 0 then
+ setfield(prev,"replace",newkern(leftkern)) -- maybe also leftkern
+ end
end
end
- end
- else
- -- cursive
- if hascursives and maxc > 0 then
- local ny = getfield(current,"yoffset")
- for i=maxc,minc,-1 do
- local ti = glyphs[i]
- ny = ny + properties[ti].cursivedy
- setfield(ti,"yoffset",getfield(ti,"yoffset") + ny) -- can be mark
+ if done then
+ setdisc(prevdisc,pre,post,replace)
end
- maxc = 0
- cursiveanchor = nil
end
end
+ else
+ -- cursive
+ if hascursives and maxc > 0 then
+ local nx, ny = getoffsets(current)
+ for i=maxc,minc,-1 do
+ local ti = glyphs[i]
+ ny = ny + properties[ti].cursivedy
+ local xi, yi = getoffsets(ti)
+ setoffsets(ti,xi,yi + ny) -- can be mark, we could use properties
+ end
+ maxc = 0
+ cursiveanchor = nil
+ end
end
prevdisc = nil
prevglyph = current
+ elseif char == false then
+ prevdisc = nil
+ prevglyph = current
elseif id == disc_code then
pre, post, replace, pretail, posttail, replacetail = getdisc(current,true)
local done = false
@@ -1258,7 +1212,7 @@ local function inject_everything(head,where)
if i then
local yoffset = i.yoffset
if yoffset and yoffset ~= 0 then
- setfield(n,"yoffset",yoffset)
+ setoffsets(n,false,yoffset)
end
local leftkern = i.leftkern
if leftkern and leftkern ~= 0 then
@@ -1290,7 +1244,7 @@ local function inject_everything(head,where)
if i then
local yoffset = i.yoffset
if yoffset and yoffset ~= 0 then
- setfield(n,"yoffset",yoffset)
+ setoffsets(n,false,yoffset)
end
local leftkern = i.leftkern
if leftkern and leftkern ~= 0 then
@@ -1322,7 +1276,7 @@ local function inject_everything(head,where)
if i then
local yoffset = i.yoffset
if yoffset and yoffset ~= 0 then
- setfield(n,"yoffset",yoffset)
+ setoffsets(n,false,yoffset)
end
local leftkern = i.leftkern
if leftkern and leftkern ~= 0 then
@@ -1390,11 +1344,11 @@ local function inject_everything(head,where)
end
-- cursive
if hascursives and maxc > 0 then
- local ny = getfield(last,"yoffset")
+ local nx, ny = getoffsets(last)
for i=maxc,minc,-1 do
local ti = glyphs[i]
ny = ny + properties[ti].cursivedy
- setfield(ti,"yoffset",ny) -- why not add ?
+ setoffsets(ti,false,ny) -- why not add ?
if trace_cursive then
showoffset(ti)
end
@@ -1470,9 +1424,9 @@ end
injections.getthreshold = getthreshold
-function injections.isspace(n,threshold)
- if getid(n) == glue_code then
- local w = getfield(n,"width")
+function injections.isspace(n,threshold,id)
+ if (id or getid(n)) == glue_code then
+ local w = getwidth(n)
if threshold and w > threshold then -- was >=
return 32
end
@@ -1531,32 +1485,32 @@ local function injectspaces(head)
end
end
if leftkern then
- local old = getfield(n,"width")
+ local old = getwidth(n)
if old > threshold then
if rightkern then
local new = old + (leftkern + rightkern) * factor
if trace_spaces then
report_spaces("%C [%p -> %p] %C",prevchar,old,new,nextchar)
end
- setfield(n,"width",new)
+ setwidth(n,new)
leftkern = false
else
local new = old + leftkern * factor
if trace_spaces then
report_spaces("%C [%p -> %p]",prevchar,old,new)
end
- setfield(n,"width",new)
+ setwidth(n,new)
end
end
leftkern = false
elseif rightkern then
- local old = getfield(n,"width")
+ local old = getwidth(n)
if old > threshold then
local new = old + rightkern * factor
if trace_spaces then
report_spaces("[%p -> %p] %C",nextchar,old,new)
end
- setfield(n,"width",new)
+ setwidth(n,new)
end
rightkern = false
end
diff --git a/tex/context/base/mkiv/font-otl.lua b/tex/context/base/mkiv/font-otl.lua
index d4eaed763..4b97a90a2 100644
--- a/tex/context/base/mkiv/font-otl.lua
+++ b/tex/context/base/mkiv/font-otl.lua
@@ -23,7 +23,7 @@ if not modules then modules = { } end modules ['font-otl'] = {
-- todo: less tounicodes
-local gmatch, find, match, lower, strip = string.gmatch, string.find, string.match, string.lower, string.strip
+local lower = string.lower
local type, next, tonumber, tostring, unpack = type, next, tonumber, tostring, unpack
local abs = math.abs
local derivetable = table.derive
@@ -127,26 +127,26 @@ function otf.load(filename,sub,featurefile) -- second argument (format) is gone
hash = hash .. "-" .. sub
end
hash = containers.cleanname(hash)
- local featurefiles
- if featurefile then
- featurefiles = { }
- for s in gmatch(featurefile,"[^,]+") do
- local name = resolvers.findfile(file.addsuffix(s,'fea'),'fea') or ""
- if name == "" then
- report_otf("loading error, no featurefile %a",s)
- else
- local attr = lfs.attributes(name)
- featurefiles[#featurefiles+1] = {
- name = name,
- size = attr and attr.size or 0,
- time = attr and attr.modification or 0,
- }
- end
- end
- if #featurefiles == 0 then
- featurefiles = nil
- end
- end
+ -- local featurefiles
+ -- if featurefile then
+ -- featurefiles = { }
+ -- for s in gmatch(featurefile,"[^,]+") do
+ -- local name = resolvers.findfile(file.addsuffix(s,'fea'),'fea') or ""
+ -- if name == "" then
+ -- report_otf("loading error, no featurefile %a",s)
+ -- else
+ -- local attr = lfs.attributes(name)
+ -- featurefiles[#featurefiles+1] = {
+ -- name = name,
+ -- size = attr and attr.size or 0,
+ -- time = attr and attr.modification or 0,
+ -- }
+ -- end
+ -- end
+ -- if #featurefiles == 0 then
+ -- featurefiles = nil
+ -- end
+ -- end
local data = containers.read(otf.cache,hash)
local reload = not data or data.size ~= size or data.time ~= time or data.tableversion ~= otfreaders.tableversion
if forceload then
@@ -252,6 +252,21 @@ function otf.load(filename,sub,featurefile) -- second argument (format) is gone
end
--
data.metadata.math = data.resources.mathconstants
+ --
+ -- delayed tables (experiment)
+ --
+ local classes = data.resources.classes
+ if not classes then
+ local descriptions = data.descriptions
+ classes = setmetatableindex(function(t,k)
+ local d = descriptions[k]
+ local v = (d and d.class or "base") or false
+ t[k] = v
+ return v
+ end)
+ data.resources.classes = classes
+ end
+ --
end
return data
diff --git a/tex/context/base/mkiv/font-ots.lua b/tex/context/base/mkiv/font-ots.lua
index 1f8421481..4d8c0fcdd 100644
--- a/tex/context/base/mkiv/font-ots.lua
+++ b/tex/context/base/mkiv/font-ots.lua
@@ -6,73 +6,45 @@ if not modules then modules = { } end modules ['font-ots'] = { -- sequences
license = "see context related readme files",
}
--- to be checked: discrun doesn't seem to do something useful now (except run the
--- check again) so if we need it again we'll do a zwnjrun or so
-
--- components will go away and be replaced by a property table which simplifies
--- code (also more efficient)
-
--- beware, on my development machine we test a slightly a more optimized version
-
--- assumptions:
---
--- cursives don't cross discretionaries
--- marks precede bases
---
--- pitfalls:
---
--- when we append to a dics field we need to set the field in order to update tail
---
--- This is a version of font-otn.lua adapted to the new font loader code. It
--- is a context version which can contain experimental code, but when we
--- have serious patches we will backport to the font-otn files. The plain
--- loader that ships with context also uses this now.
---
--- todo: looks like we have a leak somewhere (probably in ligatures)
--- todo: copy attributes to disc
--- todo: get rid of components, better use the tounicode entry if needed (at all)
---
--- we do some disc juggling where we need to keep in mind that the
--- pre, post and replace fields can have prev pointers to a nesting
--- node ... i wonder if that is still needed
---
--- not possible:
---
--- \discretionary {alpha-} {betagammadelta}
--- {\discretionary {alphabeta-} {gammadelta}
--- {\discretionary {alphabetagamma-} {delta}
--- {alphabetagammadelta}}}
-
--[[ldx--
<p>This module is a bit more split up that I'd like but since we also want to test
with plain <l n='tex'/> it has to be so. This module is part of <l n='context'/>
and discussion about improvements and functionality mostly happens on the
<l n='context'/> mailing list.</p>
-<p>The specification of OpenType is kind of vague. Apart from a lack of a proper
-free specifications there's also the problem that Microsoft and Adobe
-may have their own interpretation of how and in what order to apply features.
-In general the Microsoft website has more detailed specifications and is a
-better reference. There is also some information in the FontForge help files.</p>
+<p>The specification of OpenType is (or at least a decade ago was) kind of vague.
+Apart from a lack of a proper free specifications there's also the problem that
+Microsoft and Adobe may have their own interpretation of how and in what order to
+apply features. In general the Microsoft website has more detailed specifications
+and is a better reference. There is also some information in the FontForge help
+files. In the end we rely most on the Microsoft specification.</p>
<p>Because there is so much possible, fonts might contain bugs and/or be made to
work with certain rederers. These may evolve over time which may have the side
-effect that suddenly fonts behave differently.</p>
+effect that suddenly fonts behave differently. We don't want to catch all font
+issues.</p>
-<p>After a lot of experiments (mostly by Taco, me and Idris) we're now at yet another
-implementation. Of course all errors are mine and of course the code can be
-improved. There are quite some optimizations going on here and processing speed
-is currently acceptable. Not all functions are implemented yet, often because I
-lack the fonts for testing. Many scripts are not yet supported either, but I will
-look into them as soon as <l n='context'/> users ask for it.</p>
+<p>After a lot of experiments (mostly by Taco, me and Idris) the first implementation
+becaus quite useful. When it did most of what we wanted, a more optimized version
+evolved. Of course all errors are mine and of course the code can be improved. There
+are quite some optimizations going on here and processing speed is currently quite
+acceptable and has been improved over time. Many complex scripts are not yet supported
+yet, but I will look into them as soon as <l n='context'/> users ask for it.</p>
-<p>The specification leaves room for interpretation. In case of doubt the microsoft
+<p>The specification leaves room for interpretation. In case of doubt the Microsoft
implementation is the reference as it is the most complete one. As they deal with
lots of scripts and fonts, Kai and Ivo did a lot of testing of the generic code and
their suggestions help improve the code. I'm aware that not all border cases can be
taken care of, unless we accept excessive runtime, and even then the interference
with other mechanisms (like hyphenation) are not trivial.</p>
+<p>Especially discretionary handling has been improved much by Kai Eigner who uses complex
+(latin) fonts. The current implementation is a compromis between his patches and my code
+and in the meantime performance is quite ok. We cannot check all border cases without
+compromising speed but so far we're okay. Given good test cases we can probably improve
+it here and there. Especially chain lookups are non trivial with discretionaries but
+things got much better over time thanks to Kai.</p>
+
<p>Glyphs are indexed not by unicode but in their own way. This is because there is no
relationship with unicode at all, apart from the fact that a font might cover certain
ranges of characters. One character can have multiple shapes. However, at the
@@ -84,33 +56,74 @@ then in the output eventually.</p>
that different from the one produced by <l n='fontforge'/> but we uses hashes instead.
In <l n='context'/> that table is packed (similar tables are shared) and cached on disk
so that successive runs can use the optimized table (after loading the table is
-unpacked). The flattening code used later is a prelude to an even more compact table
-format (and as such it keeps evolving).</p>
-
-<p>This module is sparsely documented because it is a moving target. The table format
-of the reader changes and we experiment a lot with different methods for supporting
-features.</p>
+unpacked).</p>
-<p>As with the <l n='afm'/> code, we may decide to store more information in the
-<l n='otf'/> table.</p>
+<p>This module is sparsely documented because it is has been a moving target. The
+table format of the reader changed a bit over time and we experiment a lot with
+different methods for supporting features. By now the structures are quite stable</p>
<p>Incrementing the version number will force a re-cache. We jump the number by one
-when there's a fix in the <l n='fontforge'/> library or <l n='lua'/> code that
-results in different tables.</p>
+when there's a fix in the reader or processing code that can result in different
+results.</p>
+
+<p>This code is also used outside context but in context it has to work with other
+mechanisms. Both put some constraints on the code here.</p>
+
--ldx]]--
+-- Remark: We assume that cursives don't cross discretionaries which is okay because it
+-- is only used in semitic scripts.
+--
+-- Remark: We assume that marks precede base characters.
+--
+-- Remark: When complex ligatures extend into discs nodes we can get side effects. Normally
+-- this doesn't happen; ff\d{l}{l}{l} in lm works but ff\d{f}{f}{f}.
+--
+-- Todo: check if we copy attributes to disc nodes if needed.
+--
+-- Todo: it would be nice if we could get rid of components. In other places we can use
+-- the unicode properties.
+--
+-- Remark: We do some disc juggling where we need to keep in mind that the pre, post and
+-- replace fields can have prev pointers to a nesting node ... I wonder if that is still
+-- needed.
+--
+-- Remark: This is not possible:
+--
+-- \discretionary {alpha-} {betagammadelta}
+-- {\discretionary {alphabeta-} {gammadelta}
+-- {\discretionary {alphabetagamma-} {delta}
+-- {alphabetagammadelta}}}
+--
+-- Remark: Something is messed up: we have two mark / ligature indices, one at the
+-- injection end and one here ... this is based on KE's patches but there is something
+-- fishy there as I'm pretty sure that for husayni we need some connection (as it's much
+-- more complex than an average font) but I need proper examples of all cases, not of
+-- only some.
+--
+-- Remark: I wonder if indexed would be faster than unicoded. It would be a major
+-- rewrite to have char being unicode + an index field in glyph nodes. Also more
+-- assignments have to be made in order to keep things in sync. So, it's a no-go.
+--
+-- Remark: We can provide a fast loop when there are no disc nodes (tests show a 1%
+-- gain). Smaller functions might perform better cache-wise. But ... memory becomes
+-- faster anyway, so ...
+
local type, next, tonumber = type, next, tonumber
local random = math.random
local formatters = string.formatters
local insert = table.insert
-local logs, trackers, nodes, attributes = logs, trackers, nodes, attributes
+local registertracker = trackers.register
-local registertracker = trackers.register
-local registerdirective = directives.register
+local logs = logs
+local trackers = trackers
+local nodes = nodes
+local attributes = attributes
+local fonts = fonts
-local fonts = fonts
-local otf = fonts.handlers.otf
+local otf = fonts.handlers.otf
+local tracers = nodes.tracers
local trace_lookups = false registertracker("otf.lookups", function(v) trace_lookups = v end)
local trace_singles = false registertracker("otf.singles", function(v) trace_singles = v end)
@@ -124,7 +137,6 @@ local trace_cursive = false registertracker("otf.cursive", function(v
local trace_preparing = false registertracker("otf.preparing", function(v) trace_preparing = v end)
local trace_bugs = false registertracker("otf.bugs", function(v) trace_bugs = v end)
local trace_details = false registertracker("otf.details", function(v) trace_details = v end)
------ trace_applied = false registertracker("otf.applied", function(v) trace_applied = v end)
local trace_steps = false registertracker("otf.steps", function(v) trace_steps = v end)
local trace_skips = false registertracker("otf.skips", function(v) trace_skips = v end)
local trace_directions = false registertracker("otf.directions", function(v) trace_directions = v end)
@@ -135,23 +147,20 @@ local trace_discruns = false registertracker("otf.discruns", function(v
local trace_compruns = false registertracker("otf.compruns", function(v) trace_compruns = v end)
local trace_testruns = false registertracker("otf.testruns", function(v) trace_testruns = v end)
------ zwnjruns = true registerdirective("otf.zwnjruns", function(v) zwnjruns = v end)
local optimizekerns = true
-local alwaysdisc = true registerdirective("otf.alwaysdisc", function(v) alwaysdisc = v end)
-local report_direct = logs.reporter("fonts","otf direct")
-local report_subchain = logs.reporter("fonts","otf subchain")
-local report_chain = logs.reporter("fonts","otf chain")
-local report_process = logs.reporter("fonts","otf process")
-local report_warning = logs.reporter("fonts","otf warning")
-local report_run = logs.reporter("fonts","otf run")
+local report_direct = logs.reporter("fonts","otf direct")
+local report_subchain = logs.reporter("fonts","otf subchain")
+local report_chain = logs.reporter("fonts","otf chain")
+local report_process = logs.reporter("fonts","otf process")
+local report_warning = logs.reporter("fonts","otf warning")
+local report_run = logs.reporter("fonts","otf run")
registertracker("otf.replacements", "otf.singles,otf.multiples,otf.alternatives,otf.ligatures")
registertracker("otf.positions","otf.marks,otf.kerns,otf.cursive")
registertracker("otf.actions","otf.replacements,otf.positions")
registertracker("otf.injections","nodes.injections")
-
-registertracker("*otf.sample","otf.steps,otf.actions,otf.analyzing")
+registertracker("otf.sample","otf.steps,otf.actions,otf.analyzing")
local nuts = nodes.nuts
local tonode = nuts.tonode
@@ -178,6 +187,10 @@ local setchar = nuts.setchar
local getdisc = nuts.getdisc
local setdisc = nuts.setdisc
local setlink = nuts.setlink
+local getcomponents = nuts.getcomponents -- the original one, not yet node-aux
+local setcomponents = nuts.setcomponents -- the original one, not yet node-aux
+local getdir = nuts.getdir
+local getwidth = nuts.getwidth
local ischar = nuts.is_char
@@ -190,14 +203,16 @@ local flush_node = nuts.flush_node
local end_of_math = nuts.end_of_math
local traverse_nodes = nuts.traverse
local traverse_id = nuts.traverse_id
-local remove_node = nuts.remove
+local set_components = nuts.set_components
+local take_components = nuts.take_components
+local count_components = nuts.count_components
+local copy_no_components = nuts.copy_no_components
+local copy_only_glyphs = nuts.copy_only_glyphs
local setmetatableindex = table.setmetatableindex
-local zwnj = 0x200C
-local zwj = 0x200D
-local wildcard = "*"
-local default = "dflt"
+----- zwnj = 0x200C
+----- zwj = 0x200D
local nodecodes = nodes.nodecodes
local glyphcodes = nodes.glyphcodes
@@ -215,13 +230,8 @@ local ligature_code = glyphcodes.ligature
local privateattribute = attributes.private
--- Something is messed up: we have two mark / ligature indices, one at the injection
--- end and one here ... this is based on KE's patches but there is something fishy
--- there as I'm pretty sure that for husayni we need some connection (as it's much
--- more complex than an average font) but I need proper examples of all cases, not
--- of only some.
-
local a_state = privateattribute('state')
+local a_noligature = privateattribute("noligature")
local injections = nodes.injections
local setmark = injections.setmark
@@ -233,11 +243,8 @@ local copyinjection = injections.copy
local setligaindex = injections.setligaindex
local getligaindex = injections.getligaindex
-local cursonce = true
-
-local fonthashes = fonts.hashes
-local fontdata = fonthashes.identifiers
-local fontfeatures = fonthashes.features
+local fontdata = fonts.hashes.identifiers
+local fontfeatures = fonts.hashes.features
local otffeatures = fonts.constructors.features.otf
local registerotffeature = otffeatures.register
@@ -248,37 +255,36 @@ local getrandom = utilities and utilities.randomizer and utilities.rand
otf.defaultnodealternate = "none" -- first last
--- We use a few global variables. The handler can be called nested but this assumes that the
--- same font is used. Nested calls are normally not needed (only for devanagari).
-
-local tfmdata = false
-local characters = false
-local descriptions = false
-local marks = false
-local currentfont = false
-local factor = 0
-local threshold = 0
-local checkmarks = false
+-- We use a few semi-global variables. The handler can be called nested but this assumes
+-- that the same font is used.
-local sweepnode = nil
-local sweepprev = nil
-local sweepnext = nil
-local sweephead = { }
+local tfmdata = false
+local characters = false
+local descriptions = false
+local marks = false
+local classes = false
+local currentfont = false
+local factor = 0
+local threshold = 0
+local checkmarks = false
-local notmatchpre = { }
-local notmatchpost = { }
-local notmatchreplace = { }
+local sweepnode = nil
+local sweepprev = nil
+local sweepnext = nil
+local sweephead = { }
-local handlers = { }
+local notmatchpre = { }
+local notmatchpost = { }
+local notmatchreplace = { }
-local isspace = injections.isspace
-local getthreshold = injections.getthreshold
+local handlers = { }
--- we use this for special testing and documentation
+local isspace = injections.isspace
+local getthreshold = injections.getthreshold
-local checkstep = (nodes and nodes.tracers and nodes.tracers.steppers.check) or function() end
-local registerstep = (nodes and nodes.tracers and nodes.tracers.steppers.register) or function() end
-local registermessage = (nodes and nodes.tracers and nodes.tracers.steppers.message) or function() end
+local checkstep = (tracers and tracers.steppers.check) or function() end
+local registerstep = (tracers and tracers.steppers.register) or function() end
+local registermessage = (tracers and tracers.steppers.message) or function() end
local function checkdisccontent(d)
local pre, post, replace = getdisc(d)
@@ -351,6 +357,13 @@ local function mref(rlmode)
end
end
+-- The next code is somewhat complicated by the fact that some fonts can have ligatures made
+-- from ligatures that themselves have marks. This was identified by Kai in for instance
+-- arabtype: KAF LAM SHADDA ALEF FATHA (0x0643 0x0644 0x0651 0x0627 0x064E). This becomes
+-- KAF LAM-ALEF with a SHADDA on the first and a FATHA op de second component. In a next
+-- iteration this becomes a KAF-LAM-ALEF with a SHADDA on the second and a FATHA on the
+-- third component.
+
-- We can assume that languages that use marks are not hyphenated. We can also assume
-- that at most one discretionary is present.
@@ -360,21 +373,6 @@ end
-- However, for arabic we need to keep them around for the sake of mark placement
-- and indices.
-local function copy_glyph(g) -- next and prev are untouched !
- local components = getfield(g,"components")
- if components then
- setfield(g,"components")
- local n = copy_node(g)
- copyinjection(n,g) -- we need to preserve the lig indices
- setfield(g,"components",components)
- return n
- else
- local n = copy_node(g)
- copyinjection(n,g) -- we need to preserve the lig indices
- return n
- end
-end
-
local function flattendisk(head,disc)
local pre, post, replace, pretail, posttail, replacetail = getdisc(disc,true)
local prev, next = getboth(disc)
@@ -419,18 +417,40 @@ local function appenddisc(disc,list)
if post then
setlink(posttail,posthead)
else
- post = phead
+ post = posthead
end
if replace then
setlink(replacetail,replacehead)
else
- replace = rhead
+ replace = replacehead
end
setdisc(disc,pre,post,replace)
end
-- start is a mark and we need to keep that one
+local take_components = getcomponents -- we overload here (for now)
+local set_components = setcomponents -- we overload here (for now)
+----- get_components = getcomponents -- we overload here (for now)
+
+local function count_components(start,marks)
+ if getid(start) ~= glyph_code then
+ return 0
+ elseif getsubtype(start) == ligature_code then
+ local i = 0
+ local components = getcomponents(start)
+ while components do
+ i = i + count_components(components,marks)
+ components = getnext(components)
+ end
+ return i
+ elseif not marks[getchar(start)] then
+ return 1
+ else
+ return 0
+ end
+end
+
local function markstoligature(head,start,stop,char)
if start == stop and getchar(start) == char then
return head, start
@@ -439,46 +459,135 @@ local function markstoligature(head,start,stop,char)
local next = getnext(stop)
setprev(start)
setnext(stop)
- local base = copy_glyph(start)
+ local base = copy_no_components(start,copyinjection)
if head == start then
head = base
end
resetinjection(base)
setchar(base,char)
setsubtype(base,ligature_code)
- setfield(base,"components",start)
- setlink(prev,base)
- setlink(base,next)
+ set_components(base,start)
+ setlink(prev,base,next)
return head, base
end
end
--- The next code is somewhat complicated by the fact that some fonts can have ligatures made
--- from ligatures that themselves have marks. This was identified by Kai in for instance
--- arabtype: KAF LAM SHADDA ALEF FATHA (0x0643 0x0644 0x0651 0x0627 0x064E). This becomes
--- KAF LAM-ALEF with a SHADDA on the first and a FATHA op de second component. In a next
--- iteration this becomes a KAF-LAM-ALEF with a SHADDA on the second and a FATHA on the
--- third component.
-
-local function getcomponentindex(start) -- we could store this offset in the glyph (nofcomponents)
- if getid(start) ~= glyph_code then -- and then get rid of all components
- return 0
- elseif getsubtype(start) == ligature_code then
- local i = 0
- local components = getfield(start,"components")
- while components do
- i = i + getcomponentindex(components)
- components = getnext(components)
- end
- return i
- elseif not marks[getchar(start)] then
- return 1
- else
- return 0
- end
-end
-
-local a_noligature = attributes.private("noligature")
+-- local function toligature(head,start,stop,char,dataset,sequence,markflag,discfound) -- brr head
+-- if getattr(start,a_noligature) == 1 then
+-- -- so we can do: e\noligature{ff}e e\noligature{f}fie (we only look at the first)
+-- return head, start
+-- end
+-- if start == stop and getchar(start) == char then
+-- resetinjection(start)
+-- setchar(start,char)
+-- return head, start
+-- end
+-- local prev = getprev(start)
+-- local next = getnext(stop)
+-- local comp = start
+-- setprev(start)
+-- setnext(stop)
+-- local base = copy_no_components(start,copyinjection)
+-- if start == head then
+-- head = base
+-- end
+-- resetinjection(base)
+-- setchar(base,char)
+-- setsubtype(base,ligature_code)
+-- set_components(base,comp)
+-- setlink(prev,base,next)
+-- if not discfound then
+-- local deletemarks = markflag ~= "mark"
+-- local components = start
+-- local baseindex = 0
+-- local componentindex = 0
+-- local head = base
+-- local current = base
+-- -- first we loop over the glyphs in start .. stop
+-- while start do
+-- local char = getchar(start)
+-- if not marks[char] then
+-- baseindex = baseindex + componentindex
+-- componentindex = getcomponentindex(start,marks)
+-- elseif not deletemarks then -- quite fishy
+-- setligaindex(start,baseindex + getligaindex(start,componentindex))
+-- if trace_marks then
+-- logwarning("%s: keep mark %s, gets index %s",pref(dataset,sequence),gref(char),getligaindex(start))
+-- end
+-- local n = copy_node(start)
+-- copyinjection(n,start)
+-- head, current = insert_node_after(head,current,n) -- unlikely that mark has components
+-- elseif trace_marks then
+-- logwarning("%s: delete mark %s",pref(dataset,sequence),gref(char))
+-- end
+-- start = getnext(start)
+-- end
+-- -- we can have one accent as part of a lookup and another following
+-- -- local start = components -- was wrong (component scanning was introduced when more complex ligs in devanagari was added)
+-- local start = getnext(current)
+-- while start do
+-- local char = ischar(start)
+-- if char then
+-- if marks[char] then
+-- setligaindex(start,baseindex + getligaindex(start,componentindex))
+-- if trace_marks then
+-- logwarning("%s: set mark %s, gets index %s",pref(dataset,sequence),gref(char),getligaindex(start))
+-- end
+-- start = getnext(start)
+-- else
+-- break
+-- end
+-- else
+-- break
+-- end
+-- end
+-- else
+-- -- discfound ... forget about marks .. probably no scripts that hyphenate and have marks
+-- local discprev, discnext = getboth(discfound)
+-- if discprev and discnext then
+-- -- we assume normalization in context, and don't care about generic ... especially
+-- -- \- can give problems as there we can have a negative char but that won't match
+-- -- anyway
+-- local pre, post, replace, pretail, posttail, replacetail = getdisc(discfound,true)
+-- if not replace then -- todo: signal simple hyphen
+-- local prev = getprev(base)
+-- local current = comp
+-- local previous = nil
+-- local copied = nil
+-- while current do
+-- if getid(current) == glyph_code then
+-- local n = copy_node(current)
+-- if copied then
+-- setlink(previous,n)
+-- else
+-- copied = n
+-- end
+-- previous = n
+-- end
+-- current = getnext(current)
+-- end
+-- setprev(discnext) -- also blocks funny assignments
+-- setnext(discprev) -- also blocks funny assignments
+-- if pre then
+-- setlink(discprev,pre)
+-- end
+-- pre = comp
+-- if post then
+-- setlink(posttail,discnext)
+-- setprev(post)
+-- else
+-- post = discnext
+-- end
+-- setlink(prev,discfound,next)
+-- setboth(base)
+-- set_components(base,copied)
+-- setdisc(discfound,pre,post,base) -- was discretionary_code
+-- base = prev -- restart
+-- end
+-- end
+-- end
+-- return head, base
+-- end
local function toligature(head,start,stop,char,dataset,sequence,markflag,discfound) -- brr head
if getattr(start,a_noligature) == 1 then
@@ -490,33 +599,20 @@ local function toligature(head,start,stop,char,dataset,sequence,markflag,discfou
setchar(start,char)
return head, start
end
- -- needs testing (side effects):
- local components = getfield(start,"components")
- if components then
- -- we get a double free .. needs checking
- -- flush_node_list(components)
- end
- --
local prev = getprev(start)
local next = getnext(stop)
local comp = start
setprev(start)
setnext(stop)
- local base = copy_glyph(start)
+ local base = copy_no_components(start,copyinjection)
if start == head then
head = base
end
resetinjection(base)
setchar(base,char)
setsubtype(base,ligature_code)
- setfield(base,"components",comp) -- start can have components ... do we need to flush?
- if prev then
- setnext(prev,base)
- end
- if next then
- setprev(next,base)
- end
- setboth(base,prev,next)
+ set_components(base,comp)
+ setlink(prev,base,next)
if not discfound then
local deletemarks = markflag ~= "mark"
local components = start
@@ -529,7 +625,7 @@ local function toligature(head,start,stop,char,dataset,sequence,markflag,discfou
local char = getchar(start)
if not marks[char] then
baseindex = baseindex + componentindex
- componentindex = getcomponentindex(start)
+ componentindex = count_components(start,marks)
elseif not deletemarks then -- quite fishy
setligaindex(start,baseindex + getligaindex(start,componentindex))
if trace_marks then
@@ -544,7 +640,6 @@ local function toligature(head,start,stop,char,dataset,sequence,markflag,discfou
start = getnext(start)
end
-- we can have one accent as part of a lookup and another following
- -- local start = components -- was wrong (component scanning was introduced when more complex ligs in devanagari was added)
local start = getnext(current)
while start do
local char = ischar(start)
@@ -570,27 +665,14 @@ local function toligature(head,start,stop,char,dataset,sequence,markflag,discfou
-- \- can give problems as there we can have a negative char but that won't match
-- anyway
local pre, post, replace, pretail, posttail, replacetail = getdisc(discfound,true)
- if not replace then -- todo: signal simple hyphen
- local prev = getprev(base)
- local current = comp
- local previous = nil
- local copied = nil
- while current do
- if getid(current) == glyph_code then
- local n = copy_node(current)
- if copied then
- setlink(previous,n)
- else
- copied = n
- end
- previous = n
- end
- current = getnext(current)
- end
- setprev(discnext) -- also blocks funny assignments
- setnext(discprev) -- also blocks funny assignments
+ if not replace then
+ local prev = getprev(base)
+ local comp = take_components(base)
+ local copied = copy_only_glyphs(comp)
if pre then
setlink(discprev,pre)
+ else
+ setnext(discprev) -- also blocks funny assignments
end
pre = comp
if post then
@@ -598,13 +680,15 @@ local function toligature(head,start,stop,char,dataset,sequence,markflag,discfou
setprev(post)
else
post = discnext
+ setprev(discnext) -- also blocks funny assignments
end
- setlink(prev,discfound)
- setlink(discfound,next)
+ setlink(prev,discfound,next)
setboth(base)
- setfield(base,"components",copied)
- setdisc(discfound,pre,post,base) -- was discretionary_code
- base = prev -- restart
+ -- here components have a pointer so we can't free it!
+ set_components(base,copied)
+ replace = base
+ setdisc(discfound,pre,post,replace) -- was discretionary_code
+ base = prev
end
end
end
@@ -868,7 +952,6 @@ function handlers.gpos_pair(head,start,dataset,sequence,kerns,rlmode,step,i,inje
return head, start, false
else
local prev = start
- local done = false
while snext do
local nextchar = ischar(snext,currentfont)
if nextchar then
@@ -888,8 +971,7 @@ function handlers.gpos_pair(head,start,dataset,sequence,kerns,rlmode,step,i,inje
if trace_kerns then
logprocess("%s: shifting single %s by %p",pref(dataset,sequence),gref(nextchar),k)
end
- done = true
- break
+ return head, start, true
end
end
if a and #a > 0 then
@@ -906,15 +988,13 @@ function handlers.gpos_pair(head,start,dataset,sequence,kerns,rlmode,step,i,inje
logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p) as %s",pref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h,injection or "injections")
end
end
- done = true
- break
+ return head, start, true
elseif krn ~= 0 then
local k = setkern(snext,factor,rlmode,krn,injection)
if trace_kerns then
logprocess("%s: inserting kern %p between %s and %s as %s",pref(dataset,sequence),k,gref(getchar(prev)),gref(nextchar),injection or "injections")
end
- done = true
- break
+ return head, start, true
else -- can't happen
break
end
@@ -922,7 +1002,7 @@ function handlers.gpos_pair(head,start,dataset,sequence,kerns,rlmode,step,i,inje
break
end
end
- return head, start, done
+ return head, start, false
end
end
@@ -1085,7 +1165,6 @@ function handlers.gpos_mark2mark(head,start,dataset,sequence,markanchors,rlmode)
end
function handlers.gpos_cursive(head,start,dataset,sequence,exitanchors,rlmode,step,i) -- to be checked
- local done = false
local startchar = getchar(start)
if marks[startchar] then
if trace_cursive then
@@ -1093,7 +1172,7 @@ function handlers.gpos_cursive(head,start,dataset,sequence,exitanchors,rlmode,st
end
else
local nxt = getnext(start)
- while not done and nxt do
+ while nxt do
local nextchar = ischar(nxt,currentfont)
if not nextchar then
break
@@ -1111,7 +1190,7 @@ function handlers.gpos_cursive(head,start,dataset,sequence,exitanchors,rlmode,st
if trace_cursive then
logprocess("%s: moving %s to %s cursive (%p,%p) using anchor %s and bound %s in %s mode",pref(dataset,sequence),gref(startchar),gref(nextchar),dx,dy,anchor,bound,mref(rlmode))
end
- done = true
+ return head, start, true
end
end
end
@@ -1119,7 +1198,7 @@ function handlers.gpos_cursive(head,start,dataset,sequence,exitanchors,rlmode,st
end
end
end
- return head, start, done
+ return head, start, false
end
--[[ldx--
@@ -1207,10 +1286,11 @@ function chainprocs.gsub_single(head,start,stop,dataset,sequence,currentlookup,c
reportmoresteps(dataset,sequence)
end
local current = start
+ local mapping = steps[1].coverage
while current do
local currentchar = ischar(current)
if currentchar then
- local replacement = steps[1].coverage[currentchar]
+ local replacement = mapping[currentchar]
if not replacement or replacement == "" then
if trace_bugs then
logwarning("%s: no single for %s",cref(dataset,sequence,chainindex),gref(currentchar))
@@ -1282,10 +1362,11 @@ function chainprocs.gsub_alternate(head,start,stop,dataset,sequence,currentlooku
local what = dataset[1]
local value = what == true and tfmdata.shared.features[kind] or what -- todo: optimize in ctx
local current = start
+ local mapping = steps[1].coverage
while current do
local currentchar = ischar(current)
if currentchar then
- local alternatives = steps[1].coverage[currentchar]
+ local alternatives = mapping[currentchar]
if alternatives then
local choice, comment = get_alternative_glyph(current,alternatives,value)
if choice then
@@ -1437,7 +1518,6 @@ function chainprocs.gpos_pair(head,start,stop,dataset,sequence,currentlookup,rlm
local kerns = step.coverage[startchar] -- always 1 step
if kerns then
local prev = start
- local done = false
while snext do
local nextchar = ischar(snext,currentfont)
if not nextchar then
@@ -1459,8 +1539,7 @@ function chainprocs.gpos_pair(head,start,stop,dataset,sequence,currentlookup,rlm
if trace_kerns then
logprocess("%s: shifting single %s by %p",cref(dataset,sequence),gref(startchar),k)
end
- done = true
- break
+ return head, start, true
end
end
if a and #a > 0 then
@@ -1477,20 +1556,17 @@ function chainprocs.gpos_pair(head,start,stop,dataset,sequence,currentlookup,rlm
logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h)
end
end
- done = true
- break
+ return head, start, true
elseif krn ~= 0 then
local k = setkern(snext,factor,rlmode,krn)
if trace_kerns then
logprocess("%s: inserting kern %s between %s and %s",cref(dataset,sequence),k,gref(getchar(prev)),gref(nextchar))
end
- done = true
- break
+ return head, start, true
else
break
end
end
- return head, start, done
end
end
return head, start, false
@@ -1689,14 +1765,13 @@ function chainprocs.gpos_cursive(head,start,stop,dataset,sequence,currentlookup,
local startchar = getchar(start)
local exitanchors = steps[1].coverage[startchar] -- always 1 step
if exitanchors then
- local done = false
if marks[startchar] then
if trace_cursive then
logprocess("%s: ignoring cursive for mark %s",pref(dataset,sequence),gref(startchar))
end
else
local nxt = getnext(start)
- while not done and nxt do
+ while nxt do
local nextchar = ischar(nxt,currentfont)
if not nextchar then
break
@@ -1714,8 +1789,7 @@ function chainprocs.gpos_cursive(head,start,stop,dataset,sequence,currentlookup,
if trace_cursive then
logprocess("%s: moving %s to %s cursive (%p,%p) using anchor %s and bound %s in %s mode",pref(dataset,sequence),gref(startchar),gref(nextchar),dx,dy,anchor,bound,mref(rlmode))
end
- done = true
- break
+ return head, start, true
end
end
elseif trace_bugs then
@@ -1725,13 +1799,10 @@ function chainprocs.gpos_cursive(head,start,stop,dataset,sequence,currentlookup,
end
end
end
- return head, start, done
- else
- if trace_cursive and trace_details then
- logprocess("%s, cursive %s is already done",pref(dataset,sequence),gref(getchar(start)),alreadydone)
- end
- return head, start, false
+ elseif trace_cursive and trace_details then
+ logprocess("%s, cursive %s is already done",pref(dataset,sequence),gref(getchar(start)),alreadydone)
end
+ return head, start, false
end
-- what pointer to return, spec says stop
@@ -1774,7 +1845,7 @@ local function checked(head)
local current = head
while current do
if getid(current) == glue_code then
- local kern = new_kern(getfield(current,"width"))
+ local kern = new_kern(getwidth(current))
if head == current then
local next = getnext(current)
if next then
@@ -1785,8 +1856,7 @@ local function checked(head)
current = next
else
local prev, next = getboth(current)
- setlink(prev,kern)
- setlink(kern,next)
+ setlink(prev,kern,next)
flush_node(current)
current = next
end
@@ -1804,7 +1874,107 @@ local function setdiscchecked(d,pre,post,replace)
setdisc(d,pre,post,replace)
end
-local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,ck,chainproc)
+local noflags = { false, false, false, false }
+
+local function chainrun(head,start,last,dataset,sequence,rlmode,ck,skipped)
+
+ local size = ck[5] - ck[4] + 1
+ local flags = sequence.flags or noflags
+ local done = false
+ local skipmark = flags[1]
+ local chainlookups = ck[6]
+
+ -- current match
+ if chainlookups then
+ local nofchainlookups = #chainlookups
+ -- Lookups can be like { 1, false, 3 } or { false, 2 } or basically anything and
+ -- #lookups can be less than #current
+ if size == 1 then
+ -- if nofchainlookups > size then
+ -- -- bad rules
+ -- end
+ local chainlookup = chainlookups[1]
+ local chainkind = chainlookup.type
+ local chainproc = chainprocs[chainkind]
+ if chainproc then
+ local ok
+ head, start, ok = chainproc(head,start,last,dataset,sequence,chainlookup,rlmode,1)
+ if ok then
+ done = true
+ end
+ else
+ logprocess("%s: %s is not yet supported (1)",cref(dataset,sequence),chainkind)
+ end
+ else
+ -- See LookupType 5: Contextual Substitution Subtable. Now it becomes messy. The
+ -- easiest case is where #current maps on #lookups i.e. one-to-one. But what if
+ -- we have a ligature. Cf the spec we then need to advance one character but we
+ -- really need to test it as there are fonts out there that are fuzzy and have
+ -- too many lookups:
+ --
+ -- U+1105 U+119E U+1105 U+119E : sourcehansansklight: script=hang ccmp=yes
+ --
+ local i = 1
+ while start do
+ if skipped then
+ while start do
+ local char = getchar(start)
+ local class = classes[char]
+ if class then
+ if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then
+ start = getnext(start)
+ else
+ break
+ end
+ else
+ break
+ end
+ end
+ end
+ local chainlookup = chainlookups[i]
+ if chainlookup then
+ local chainkind = chainlookup.type
+ local chainproc = chainprocs[chainkind]
+ if chainproc then
+ local ok, n
+ head, start, ok, n = chainproc(head,start,last,dataset,sequence,chainlookup,rlmode,i)
+ -- messy since last can be changed !
+ if ok then
+ done = true
+ if n and n > 1 and i + n > nofchainlookups then
+ -- this is a safeguard, we just ignore the rest of the lookups
+ break
+ end
+ end
+ else
+ -- actually an error
+ logprocess("%s: %s is not yet supported (2)",cref(dataset,sequence),chainkind)
+ end
+ end
+ i = i + 1
+ if i > size or not start then
+ break
+ elseif start then
+ start = getnext(start)
+ end
+ end
+ end
+ else
+ -- todo: needs checking for holes in the replacements
+ local replacements = ck[7]
+ if replacements then
+ head, start, done = reversesub(head,start,last,dataset,sequence,replacements,rlmode)
+ else
+ done = true
+ if trace_contexts then
+ logprocess("%s: skipping match",cref(dataset,sequence))
+ end
+ end
+ end
+ return head, start, done
+end
+
+local function chaindisk(head,start,dataset,sequence,rlmode,ck,skipped)
if not start then
return head, start, false
@@ -1819,7 +1989,6 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
local sweepnode = sweepnode
local sweeptype = sweeptype
local sweepoverflow = false
- local checkdisc = getprev(head) -- hm bad name head
local keepdisc = not sweepnode
local lookaheaddisc = nil
local backtrackdisc = nil
@@ -1845,19 +2014,23 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
hasglue = true
elseif id == disc_code then
if keepdisc then
- keepdisc = false
- if notmatchpre[current] ~= notmatchreplace[current] then
- lookaheaddisc = current
- end
+ keepdisc = false
+ lookaheaddisc = current
local replace = getfield(current,"replace")
- while replace and i <= l do
- if getid(replace) == glyph_code then
- i = i + 1
+ if not replace then
+ sweepoverflow = true
+ sweepnode = current
+ current = getnext(current)
+ else
+ while replace and i <= l do
+ if getid(replace) == glyph_code then
+ i = i + 1
+ end
+ replace = getnext(replace)
end
- replace = getnext(replace)
+ current = getnext(replace)
end
- last = current
- current = getnext(c)
+ last = current
else
head, current = flattendisk(head,current)
end
@@ -1919,7 +2092,8 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
if notmatchpre[current] ~= notmatchreplace[current] then
lookaheaddisc = current
end
- local replace = getfield(c,"replace")
+ -- we assume a simple text only replace (we could use nuts.count)
+ local replace = getfield(current,"replace")
while replace and i < s do
if getid(replace) == glyph_code then
i = i + 1
@@ -1964,6 +2138,7 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
if notmatchpost[current] ~= notmatchreplace[current] then
backtrackdisc = current
end
+ -- we assume a simple text only replace (we could use nuts.count)
local replace = getfield(current,"replace")
while replace and i > 1 do
if getid(replace) == glyph_code then
@@ -1982,7 +2157,8 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
end
end
- local ok = false
+ local done = false
+
if lookaheaddisc then
local cf = start
@@ -2001,11 +2177,7 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
break
end
end
-
- setprev(lookaheaddisc,cprev)
- if cprev then
- setnext(cprev,lookaheaddisc)
- end
+ setlink(cprev,lookaheaddisc)
setprev(cf)
setnext(cl)
if startishead then
@@ -2014,25 +2186,35 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
local pre, post, replace = getdisc(lookaheaddisc)
local new = copy_node_list(cf)
local cnew = new
+ if pre then
+ setlink(find_node_tail(cf),pre)
+ end
+ if replace then
+ local tail = find_node_tail(new)
+ setlink(tail,replace)
+ end
for i=1,insertedmarks do
cnew = getnext(cnew)
end
+ cl = start
local clast = cnew
for i=f,l do
+ cl = getnext(cl)
clast = getnext(clast)
end
if not notmatchpre[lookaheaddisc] then
- cf, start, ok = chainproc(cf,start,last,dataset,sequence,chainlookup,rlmode,k)
+ local ok = false
+ cf, start, ok = chainrun(cf,start,cl,dataset,sequence,rlmode,ck,skipped)
+ if ok then
+ done = true
+ end
end
if not notmatchreplace[lookaheaddisc] then
- new, cnew, ok = chainproc(new,cnew,clast,dataset,sequence,chainlookup,rlmode,k)
- end
- if pre then
- setlink(cl,pre)
- end
- if replace then
- local tail = find_node_tail(new)
- setlink(tail,replace)
+ local ok = false
+ new, cnew, ok = chainrun(new,cnew,clast,dataset,sequence,rlmode,ck,skipped)
+ if ok then
+ done = true
+ end
end
if hasglue then
setdiscchecked(lookaheaddisc,cf,post,new)
@@ -2041,7 +2223,7 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
end
start = getprev(lookaheaddisc)
sweephead[cf] = getnext(clast)
- sweephead[new] = getnext(last)
+ sweephead[new] = getnext(cl)
elseif backtrackdisc then
@@ -2077,10 +2259,18 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
clast = getnext(clast)
end
if not notmatchpost[backtrackdisc] then
- cf, start, ok = chainproc(cf,start,last,dataset,sequence,chainlookup,rlmode,k)
+ local ok = false
+ cf, start, ok = chainrun(cf,start,last,dataset,sequence,rlmode,ck,skipped)
+ if ok then
+ done = true
+ end
end
if not notmatchreplace[backtrackdisc] then
- new, cnew, ok = chainproc(new,cnew,clast,dataset,sequence,chainlookup,rlmode,k)
+ local ok = false
+ new, cnew, ok = chainrun(new,cnew,clast,dataset,sequence,rlmode,ck,skipped)
+ if ok then
+ done = true
+ end
end
if post then
setlink(posttail,cf)
@@ -2103,21 +2293,34 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
else
- head, start, ok = chainproc(head,start,last,dataset,sequence,chainlookup,rlmode,k)
+ local ok = false
+ head, start, ok = chainrun(head,start,last,dataset,sequence,rlmode,ck,skipped)
+ if ok then
+ done = true
+ end
end
- return head, start, ok
+ return head, start, done
end
-local noflags = { false, false, false, false }
+local function chaintrac(head,start,dataset,sequence,rlmode,ck,skipped)
+ local rule = ck[1]
+ local lookuptype = ck[8] or ck[2]
+ local nofseq = #ck[3]
+ local first = ck[4]
+ local last = ck[5]
+ local char = getchar(start)
+ logwarning("%s: rule %s matches at char %s for (%s,%s,%s) chars, lookuptype %a",
+ cref(dataset,sequence),rule,gref(char),first-1,last-first+1,nofseq-last,lookuptype)
+end
local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
local sweepnode = sweepnode
local sweeptype = sweeptype
local currentfont = currentfont
local diskseen = false
- local checkdisc = getprev(head)
+ local checkdisc = sweeptype and getprev(head)
local flags = sequence.flags or noflags
local done = false
local skipmark = flags[1]
@@ -2125,6 +2328,8 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
local skipbase = flags[3]
local markclass = sequence.markclass
local skipped = false
+ local startprev,
+ startnext = getboth(start)
for k=1,#contexts do -- i've only seen ccmp having > 1 (e.g. dejavu)
local match = true
local current = start
@@ -2138,7 +2343,9 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
-- this seldom happens as it makes no sense (bril, ebgaramond, husayni, minion)
local char = ischar(current,currentfont)
if char then
- match = seq[1][char]
+ if not seq[1][char] then
+ match = false
+ end
end
else
-- maybe we need a better space check (maybe check for glue or category or combination)
@@ -2151,7 +2358,8 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
-- before/current/after | before/current | current/after
local discfound = nil
local n = f + 1
- last = getnext(last) -- the second in current (first already matched)
+ -- last = getnext(last) -- the second in current (first already matched)
+ last = startnext -- the second in current (first already matched)
while n <= l do
if not last and (sweeptype == "post" or sweeptype == "replace") then
last = getnext(sweepnode)
@@ -2160,9 +2368,8 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
if last then
local char, id = ischar(last,currentfont)
if char then
- local ccd = descriptions[char]
- if ccd then
- local class = ccd.class or "base"
+ local class = classes[char]
+ if class then
if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then
skipped = true
if trace_skips then
@@ -2177,7 +2384,9 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
else
if discfound then
notmatchreplace[discfound] = true
- match = not notmatchpre[discfound]
+ if notmatchpre[discfound] then
+ match = false
+ end
else
match = false
end
@@ -2186,7 +2395,9 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
else
if discfound then
notmatchreplace[discfound] = true
- match = not notmatchpre[discfound]
+ if notmatchpre[discfound] then
+ match = false
+ end
else
match = false
end
@@ -2195,7 +2406,9 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
elseif char == false then
if discfound then
notmatchreplace[discfound] = true
- match = not notmatchpre[discfound]
+ if notmatchpre[discfound] then
+ match = false
+ end
else
match = false
end
@@ -2238,11 +2451,16 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
end
else
notmatchreplace[last] = true
- match = not notmatchpre[last]
+ if notmatchpre[last] then
+ match = false
+ end
break
end
end
- match = not notmatchpre[last]
+ -- why here again
+ if notmatchpre[last] then
+ match = false
+ end
end
-- maybe only if match
last = getnext(last)
@@ -2258,8 +2476,10 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
end
-- before
if match and f > 1 then
- local prev = getprev(start)
- if prev then
+ -- local prev = getprev(start)
+ -- if prev then
+ if startprev then
+ local prev = startprev
if prev == checkdisc and (sweeptype == "pre" or sweeptype == "replace") then
prev = getprev(sweepnode)
-- sweeptype = nil
@@ -2271,24 +2491,25 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
if prev then
local char, id = ischar(prev,currentfont)
if char then
- local ccd = descriptions[char]
- if ccd then
- local class = ccd.class
+ local class = classes[char]
+ if class then
if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then
skipped = true
if trace_skips then
show_skip(dataset,sequence,char,ck,class)
end
- prev = getprev(prev) -- moved here
+ prev = getprev(prev)
elseif seq[n][char] then
- if n > 1 then -- new test
- prev = getprev(prev) -- moved here
+ if n > 1 then
+ prev = getprev(prev)
end
n = n - 1
else
if discfound then
notmatchreplace[discfound] = true
- match = not notmatchpost[discfound]
+ if notmatchpost[discfound] then
+ match = false
+ end
else
match = false
end
@@ -2297,17 +2518,20 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
else
if discfound then
notmatchreplace[discfound] = true
- match = not notmatchpost[discfound]
+ if notmatchpost[discfound] then
+ match = false
+ end
else
match = false
end
break
end
- -- prev = getprev(prev) -- moved up
elseif char == false then
if discfound then
notmatchreplace[discfound] = true
- match = not notmatchpost[discfound]
+ if notmatchpost[discfound] then
+ match = false
+ end
else
match = false
end
@@ -2360,7 +2584,9 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
end
else
notmatchreplace[prev] = true
- match = not notmatchpost[prev]
+ if notmatchpost[prev] then
+ match = false
+ end
break
end
end
@@ -2371,7 +2597,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
end
-- maybe only if match
prev = getprev(prev)
- elseif seq[n][32] and isspace(prev,threshold) then
+ elseif seq[n][32] and id == glue_code and isspace(prev,threshold,id) then
n = n - 1
prev = getprev(prev)
else
@@ -2407,9 +2633,8 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
if current then
local char, id = ischar(current,currentfont)
if char then
- local ccd = descriptions[char]
- if ccd then
- local class = ccd.class
+ local class = classes[char]
+ if class then
if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then
skipped = true
if trace_skips then
@@ -2424,7 +2649,9 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
else
if discfound then
notmatchreplace[discfound] = true
- match = not notmatchpre[discfound]
+ if notmatchpre[discfound] then
+ match = false
+ end
else
match = false
end
@@ -2433,7 +2660,9 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
else
if discfound then
notmatchreplace[discfound] = true
- match = not notmatchpre[discfound]
+ if notmatchpre[discfound] then
+ match = false
+ end
else
match = false
end
@@ -2442,7 +2671,9 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
elseif char == false then
if discfound then
notmatchreplace[discfound] = true
- match = not notmatchpre[discfound]
+ if notmatchpre[discfound] then
+ match = false
+ end
else
match = false
end
@@ -2485,7 +2716,10 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
end
else
notmatchreplace[current] = true
- match = notmatchpre[current]
+ -- different than others, needs checking if "not" is okay
+ if not notmatchpre[current] then
+ match = false
+ end
break
end
end
@@ -2497,7 +2731,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
end
-- maybe only if match
current = getnext(current)
- elseif seq[n][32] and isspace(current,threshold) then
+ elseif seq[n][32] and id == glue_code and isspace(current,threshold,id) then
n = n + 1
current = getnext(current)
else
@@ -2515,112 +2749,13 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
end
end
if match then
- -- Can lookups be of a different type?
- local diskchain = diskseen or sweepnode
if trace_contexts then
- local rule = ck[1]
- local lookuptype = ck[8] or ck[2]
- local first = ck[4]
- local last = ck[5]
- local char = getchar(start)
- logwarning("%s: rule %s matches at char %s for (%s,%s,%s) chars, lookuptype %a",
- cref(dataset,sequence),rule,gref(char),first-1,last-first+1,s-last,lookuptype)
- end
- local chainlookups = ck[6]
- if chainlookups then
- local nofchainlookups = #chainlookups
- -- Lookups can be like { 1, false, 3 } or { false, 2 } or basically anything and
- -- #lookups can be less than #current
- if size == 1 then
- -- if nofchainlookups > size then
- -- -- bad rules
- -- end
- local chainlookup = chainlookups[1]
- local chainkind = chainlookup.type
- local chainproc = chainprocs[chainkind]
- if chainproc then
- local ok
- if diskchain then
- head, start, ok = chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,1,ck,chainproc)
- else
- head, start, ok = chainproc(head,start,last,dataset,sequence,chainlookup,rlmode,1)
- end
- if ok then
- done = true
- end
- else
- logprocess("%s: %s is not yet supported (1)",cref(dataset,sequence),chainkind)
- end
- else
- -- See LookupType 5: Contextual Substitution Subtable. Now it becomes messy. The
- -- easiest case is where #current maps on #lookups i.e. one-to-one. But what if
- -- we have a ligature. Cf the spec we then need to advance one character but we
- -- really need to test it as there are fonts out there that are fuzzy and have
- -- too many lookups:
- --
- -- U+1105 U+119E U+1105 U+119E : sourcehansansklight: script=hang ccmp=yes
- --
- local i = 1
- while start do
- if skipped then
- while start do -- todo: use properties
- local char = getchar(start)
- local ccd = descriptions[char]
- if ccd then
- local class = ccd.class or "base"
- if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then
- start = getnext(start)
- else
- break
- end
- else
- break
- end
- end
- end
- local chainlookup = chainlookups[i]
- if chainlookup then
- local chainkind = chainlookup.type
- local chainproc = chainprocs[chainkind]
- if chainproc then
- local ok, n
- if diskchain then
- head, start, ok = chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,i,ck,chainproc)
- else
- head, start, ok, n = chainproc(head,start,last,dataset,sequence,chainlookup,rlmode,i)
- end
- -- messy since last can be changed !
- if ok then
- done = true
- if n and n > 1 and i + n > nofchainlookups then
- -- this is a safeguard, we just ignore the rest of the lookups
- break
- end
- end
- else
- -- actually an error
- logprocess("%s: %s is not yet supported (2)",cref(dataset,sequence),chainkind)
- end
- end
- i = i + 1
- if i > size or not start then
- break
- elseif start then
- start = getnext(start)
- end
- end
- end
+ chaintrac(head,start,dataset,sequence,rlmode,ck,skipped)
+ end
+ if diskseen or sweepnode then
+ head, start, done = chaindisk(head,start,dataset,sequence,rlmode,ck,skipped)
else
- -- todo: needs checking for holes in the replacements
- local replacements = ck[7]
- if replacements then
- head, start, done = reversesub(head,start,last,dataset,sequence,replacements,rlmode)
- else
- done = true
- if trace_contexts then
- logprocess("%s: skipping match",cref(dataset,sequence))
- end
- end
+ head, start, done = chainrun(head,start,last,dataset,sequence,rlmode,ck,skipped)
end
if done then
break -- out of contexts (new, needs checking)
@@ -2693,79 +2828,86 @@ end)
-- fonts.hashes.sequences = sequencelists
-local autofeatures = fonts.analyzers.features
-local featuretypes = otf.tables.featuretypes
-local defaultscript = otf.features.checkeddefaultscript
-local defaultlanguage = otf.features.checkeddefaultlanguage
-
-local function initialize(sequence,script,language,enabled,autoscript,autolanguage)
- local features = sequence.features
- if features then
- local order = sequence.order
- if order then
- local featuretype = featuretypes[sequence.type or "unknown"]
- for i=1,#order do
- local kind = order[i]
- local valid = enabled[kind]
- if valid then
- local scripts = features[kind]
- local languages = scripts and (
- scripts[script] or
- scripts[wildcard] or
- (autoscript and defaultscript(featuretype,autoscript,scripts))
- )
- local enabled = languages and (
- languages[language] or
- languages[wildcard] or
- (autolanguage and defaultlanguage(featuretype,autolanguage,languages))
- )
- if enabled then
- return { valid, autofeatures[kind] or false, sequence, kind }
+do -- overcome local limit
+
+ local autofeatures = fonts.analyzers.features
+ local featuretypes = otf.tables.featuretypes
+ local defaultscript = otf.features.checkeddefaultscript
+ local defaultlanguage = otf.features.checkeddefaultlanguage
+
+ local wildcard = "*"
+ local default = "dflt"
+
+ local function initialize(sequence,script,language,enabled,autoscript,autolanguage)
+ local features = sequence.features
+ if features then
+ local order = sequence.order
+ if order then
+ local featuretype = featuretypes[sequence.type or "unknown"]
+ for i=1,#order do
+ local kind = order[i]
+ local valid = enabled[kind]
+ if valid then
+ local scripts = features[kind]
+ local languages = scripts and (
+ scripts[script] or
+ scripts[wildcard] or
+ (autoscript and defaultscript(featuretype,autoscript,scripts))
+ )
+ local enabled = languages and (
+ languages[language] or
+ languages[wildcard] or
+ (autolanguage and defaultlanguage(featuretype,autolanguage,languages))
+ )
+ if enabled then
+ return { valid, autofeatures[kind] or false, sequence, kind }
+ end
end
end
- end
- else
- -- can't happen
- end
- end
- return false
-end
-
-function otf.dataset(tfmdata,font) -- generic variant, overloaded in context
- local shared = tfmdata.shared
- local properties = tfmdata.properties
- local language = properties.language or "dflt"
- local script = properties.script or "dflt"
- local enabled = shared.features
- local autoscript = enabled and enabled.autoscript
- local autolanguage = enabled and enabled.autolanguage
- local res = resolved[font]
- if not res then
- res = { }
- resolved[font] = res
- end
- local rs = res[script]
- if not rs then
- rs = { }
- res[script] = rs
- end
- local rl = rs[language]
- if not rl then
- rl = {
- -- indexed but we can also add specific data by key
- }
- rs[language] = rl
- local sequences = tfmdata.resources.sequences
- if sequences then
- for s=1,#sequences do
- local v = enabled and initialize(sequences[s],script,language,enabled,autoscript,autolanguage)
- if v then
- rl[#rl+1] = v
+ else
+ -- can't happen
+ end
+ end
+ return false
+ end
+
+ function otf.dataset(tfmdata,font) -- generic variant, overloaded in context
+ local shared = tfmdata.shared
+ local properties = tfmdata.properties
+ local language = properties.language or "dflt"
+ local script = properties.script or "dflt"
+ local enabled = shared.features
+ local autoscript = enabled and enabled.autoscript
+ local autolanguage = enabled and enabled.autolanguage
+ local res = resolved[font]
+ if not res then
+ res = { }
+ resolved[font] = res
+ end
+ local rs = res[script]
+ if not rs then
+ rs = { }
+ res[script] = rs
+ end
+ local rl = rs[language]
+ if not rl then
+ rl = {
+ -- indexed but we can also add specific data by key
+ }
+ rs[language] = rl
+ local sequences = tfmdata.resources.sequences
+ if sequences then
+ for s=1,#sequences do
+ local v = enabled and initialize(sequences[s],script,language,enabled,autoscript,autolanguage)
+ if v then
+ rl[#rl+1] = v
+ end
end
end
end
+ return rl
end
- return rl
+
end
local function report_disc(what,n)
@@ -2851,7 +2993,7 @@ local function kernrun(disc,k_run,font,attr,...)
done = true
end
setprev(replace,nest)
--- setprev(replace)
+ -- setprev(replace)
setnext(prev,disc)
end
if next then
@@ -2867,13 +3009,15 @@ local function kernrun(disc,k_run,font,attr,...)
if k_run(prevmarks,"emptyinjections",next,font,attr,...) then
done = true
end
- setlink(prev,disc)
- setlink(disc,next)
+ setlink(prev,disc,next)
end
return nextstart, done
end
-local function comprun(disc,c_run,...)
+-- fonts like ebgaramond do ligatuires this way (less efficient than e.g. dejavu which
+-- will do the testrun variant)
+
+local function comprun(disc,c_run,...) -- vararg faster than the whole list
if trace_compruns then
report_disc("comp",disc)
end
@@ -2883,7 +3027,7 @@ local function comprun(disc,c_run,...)
--
if pre then
sweepnode = disc
- sweeptype = "pre" -- in alternative code preinjections is uc_c_sed (also used then for proeprties, saves a variable)
+ sweeptype = "pre" -- in alternative code preinjections is uc_c_sed (also used then for properties, saves a variable)
local new, done = c_run(pre,...)
if done then
pre = new
@@ -2997,41 +3141,6 @@ local function testrun(disc,t_run,c_run,...)
end
end
--- A discrun happens when we have a zwnj. We're gpossing so it is unlikely that
--- there has been a match changing the character. Now, as we check again here
--- the question is: why do we do this ... needs checking as drun seems useless
--- ... maybe that code can go away
-
--- local function discrun(disc,drun,krun)
--- local prev, next = getboth(disc)
--- if trace_discruns then
--- report_disc("disc",disc)
--- end
--- if next and prev then
--- setnext(prev,next)
--- -- setprev(next,prev)
--- drun(prev)
--- setnext(prev,disc)
--- -- setprev(next,disc)
--- end
--- --
--- if krun then -- currently always false
--- local pre = getfield(disc,"pre")
--- if not pre then
--- -- go on
--- elseif prev then
--- local nest = getprev(pre)
--- setlink(prev,pre)
--- krun(prev,"preinjections")
--- setprev(pre,nest)
--- setnext(prev,disc)
--- else
--- krun(pre,"preinjections")
--- end
--- end
--- return next
--- end
-
-- We can make some assumptions with respect to discretionaries. First of all it is very
-- unlikely that some of the analysis related attributes applies. Then we can also assume
-- that the ConTeXt specific dynamic attribute is different, although we do use explicit
@@ -3057,6 +3166,7 @@ end
-- 1{2{\oldstyle\discretionary{3}{4}{5}}6}7\par
-- 1{2\discretionary{3{\oldstyle3}}{{\oldstyle4}4}{5{\oldstyle5}5}6}7\par
+
local nesting = 0
local function c_run_single(head,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
@@ -3071,7 +3181,10 @@ local function c_run_single(head,font,attr,lookupcache,step,dataset,sequence,rlm
while start do
local char = ischar(start,font)
if char then
- local a = attr and getattr(start,0)
+ local a -- happens often so no assignment is faster
+ if attr then
+ a = getattr(start,0)
+ end
if not a or (a == attr) then
local lookupmatch = lookupcache[char]
if lookupmatch then
@@ -3105,12 +3218,16 @@ local function t_run_single(start,stop,font,attr,lookupcache)
while start ~= stop do
local char = ischar(start,font)
if char then
- local a = attr and getattr(start,0)
+ local a -- happens often so no assignment is faster
+ if attr then
+ a = getattr(start,0)
+ end
+ local startnext = getnext(start)
if not a or (a == attr) then
local lookupmatch = lookupcache[char]
if lookupmatch then -- hm, hyphens can match (tlig) so we need to really check
-- if we need more than ligatures we can outline the code and use functions
- local s = getnext(start)
+ local s = startnext
local l = nil
local d = 0
while s do
@@ -3134,32 +3251,18 @@ local function t_run_single(start,stop,font,attr,lookupcache)
else
-- go on can be a mixed one
end
- start = getnext(start)
+ start = starttnext
else
break
end
end
end
--- local function d_run_single(prev,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
--- local a = attr and getattr(prev,0)
--- if not a or (a == attr) then
--- local char = ischar(prev) -- can be disc
--- if char then
--- local lookupmatch = lookupcache[char]
--- if lookupmatch then
--- local h, d, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,1)
--- if ok then
--- done = true
--- success = true
--- end
--- end
--- end
--- end
--- end
-
local function k_run_single(sub,injection,last,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
- local a = attr and getattr(sub,0)
+ local a -- happens often so no assignment is faster
+ if attr then
+ a = getattr(sub,0)
+ end
if not a or (a == attr) then
for n in traverse_nodes(sub) do -- only gpos
if n == last then
@@ -3191,7 +3294,10 @@ local function c_run_multiple(head,font,attr,steps,nofsteps,dataset,sequence,rlm
while start do
local char = ischar(start,font)
if char then
- local a = attr and getattr(start,0)
+ local a -- happens often so no assignment is faster
+ if attr then
+ a = getattr(start,0)
+ end
if not a or (a == attr) then
for i=1,nofsteps do
local step = steps[i]
@@ -3239,7 +3345,11 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps)
while start ~= stop do
local char = ischar(start,font)
if char then
- local a = attr and getattr(start,0)
+ local a -- happens often so no assignment is faster
+ if attr then
+ a = getattr(start,0)
+ end
+ local startnext = getnext(start)
if not a or (a == attr) then
for i=1,nofsteps do
local step = steps[i]
@@ -3248,7 +3358,7 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps)
local lookupmatch = lookupcache[char]
if lookupmatch then
-- if we need more than ligatures we can outline the code and use functions
- local s = getnext(start)
+ local s = startnext
local l = nil
local d = 0
while s do
@@ -3276,41 +3386,18 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps)
else
-- go on can be a mixed one
end
- start = getnext(start)
+ start = startnext
else
break
end
end
end
--- local function d_run_multiple(prev,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
--- local a = attr and getattr(prev,0)
--- if not a or (a == attr) then
--- local char = ischar(prev) -- can be disc
--- if char then
--- for i=1,nofsteps do
--- local step = steps[i]
--- local lookupcache = step.coverage
--- if lookupcache then
--- local lookupmatch = lookupcache[char]
--- if lookupmatch then
--- -- we could move all code inline but that makes things even more unreadable
--- local h, d, ok = handler(head,prev,dataset,sequence,lookupmatch,rlmode,step,i)
--- if ok then
--- done = true
--- break
--- end
--- end
--- else
--- report_missing_coverage(dataset,sequence)
--- end
--- end
--- end
--- end
--- end
-
local function k_run_multiple(sub,injection,last,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
- local a = attr and getattr(sub,0)
+ local a -- happens often so no assignment is faster
+ if attr then
+ a = getattr(sub,0)
+ end
if not a or (a == attr) then
for n in traverse_nodes(sub) do -- only gpos
if n == last then
@@ -3342,7 +3429,7 @@ end
-- so maybe we no longer need a stack
local function txtdirstate(start,stack,top,rlparmode)
- local dir = getfield(start,"dir")
+ local dir = getdir(start)
local new = 1
if dir == "+TRT" then
top = top + 1
@@ -3366,7 +3453,7 @@ local function txtdirstate(start,stack,top,rlparmode)
end
local function pardirstate(start)
- local dir = getfield(start,"dir")
+ local dir = getdir(start)
local new = 0
if dir == "TLT" then
new = 1
@@ -3394,15 +3481,16 @@ local function featuresprocessor(head,font,attr)
nesting = nesting + 1
if nesting == 1 then
-
- currentfont = font
- tfmdata = fontdata[font]
- descriptions = tfmdata.descriptions
- characters = tfmdata.characters
- marks = tfmdata.resources.marks
+ currentfont = font
+ tfmdata = fontdata[font]
+ descriptions = tfmdata.descriptions -- only needed in gref so we could pass node there instead
+ characters = tfmdata.characters -- but this branch is not entered that often anyway
+ local resources = tfmdata.resources
+ marks = resources.marks
+ classes = resources.classes
threshold,
- factor = getthreshold(font)
- checkmarks = tfmdata.properties.checkmarks
+ factor = getthreshold(font)
+ checkmarks = tfmdata.properties.checkmarks
elseif currentfont ~= font then
@@ -3427,14 +3515,9 @@ local function featuresprocessor(head,font,attr)
end
local rlmode = 0
-
local done = false
local datasets = otf.dataset(tfmdata,font,attr)
-
- local forcedisc = alwaysdisc or not attr
-
local dirstack = { } -- could move outside function but we can have local runs
-
sweephead = { }
-- We could work on sub start-stop ranges instead but I wonder if there is that
@@ -3442,8 +3525,8 @@ local function featuresprocessor(head,font,attr)
-- to keep track of directions anyway. Also at some point I want to play with
-- font interactions and then we do need the full sweeps.
- -- Keeping track of the headnode is needed for devanagari (I generalized it a bit
- -- so that multiple cases are also covered.)
+ -- Keeping track of the headnode is needed for devanagari. (I generalized it a bit
+ -- so that multiple cases are also covered.) We could prepend a temp node.
-- We don't goto the next node when a disc node is created so that we can then treat
-- the pre, post and replace. It's a bit of a hack but works out ok for most cases.
@@ -3455,7 +3538,6 @@ local function featuresprocessor(head,font,attr)
local sequence = dataset[3] -- sequences[s] -- also dataset[5]
local rlparmode = 0
local topstack = 0
- local success = false
local typ = sequence.type
local gpossing = typ == "gpos_single" or typ == "gpos_pair" -- store in dataset
local handler = handlers[typ]
@@ -3465,7 +3547,7 @@ local function featuresprocessor(head,font,attr)
-- this permits injection, watch the different arguments
local h, d, ok = handler(head,head,dataset,sequence,nil,nil,nil,0,font,attr)
if ok then
- success = true
+ done = true
if h then
head = h
end
@@ -3476,7 +3558,10 @@ local function featuresprocessor(head,font,attr)
while start do
local char = ischar(start,font)
if char then
- local a = attr and getattr(start,0)
+ local a -- happens often so no assignment is faster
+ if attr then
+ a = getattr(start,0)
+ end
if not a or (a == attr) then
for i=1,nofsteps do
local step = steps[i]
@@ -3488,7 +3573,7 @@ local function featuresprocessor(head,font,attr)
local ok
head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i)
if ok then
- success = true
+ done = true
break
end
end
@@ -3518,11 +3603,19 @@ local function featuresprocessor(head,font,attr)
while start do
local char, id = ischar(start,font)
if char then
- local a = attr and getattr(start,0)
- if a then
- a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
- else
- a = not attribute or getprop(start,a_state) == attribute
+ -- local a = attr and getattr(start,0)
+ -- if a then
+ -- a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
+ -- else
+ -- a = not attribute or getprop(start,a_state) == attribute
+ -- end
+ local a -- happens often so no assignment is faster
+ if attr then
+ if getattr(start,0) == attr and (not attribute or getprop(start,a_state) == attribute) then
+ a = true
+ end
+ elseif not attribute or getprop(start,a_state) == attribute then
+ a = true
end
if a then
local lookupmatch = lookupcache[char]
@@ -3530,12 +3623,8 @@ local function featuresprocessor(head,font,attr)
local ok
head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,1)
if ok then
- success = true
- -- elseif gpossing and zwnjruns and char == zwnj then
- -- discrun(start,d_run,font,attr,lookupcache)
+ done = true
end
- -- elseif gpossing and zwnjruns and char == zwnj then
- -- discrun(start,d_run,font,attr,lookupcache)
end
if start then
start = getnext(start)
@@ -3547,26 +3636,16 @@ local function featuresprocessor(head,font,attr)
-- whatever glyph
start = getnext(start)
elseif id == disc_code then
- -- ctx: we could assume the same attr as the surrounding glyphs but then we loose
- -- the option to have interesting disc nodes (we gain upto 10% on extreme tests);
- -- if a disc would have a font field we could even be more strict (see oldstyle test
- -- case)
- local a = forcedisc or getsubtype(start) == discretionary_code or getattr(start,0) == attr
- if a then
- -- local attr = false
- local ok
- if gpossing then
- start, ok = kernrun(start,k_run_single, font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
- elseif typ == "gsub_ligature" then
- start, ok = testrun(start,t_run_single,c_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
- else
- start, ok = comprun(start,c_run_single, font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
- end
- if ok then
- success = true
- end
+ local ok
+ if gpossing then
+ start, ok = kernrun(start,k_run_single, font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
+ elseif typ == "gsub_ligature" then
+ start, ok = testrun(start,t_run_single,c_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
else
- start = getnext(start)
+ start, ok = comprun(start,c_run_single, font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
+ end
+ if ok then
+ done = true
end
elseif id == math_code then
start = getnext(end_of_math(start))
@@ -3581,15 +3660,22 @@ local function featuresprocessor(head,font,attr)
end
else
-
while start do
local char, id = ischar(start,font)
if char then
- local a = attr and getattr(start,0)
- if a then
- a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
- else
- a = not attribute or getprop(start,a_state) == attribute
+ -- local a = attr and getattr(start,0)
+ -- if a then
+ -- a = (a == attr) and (not attribute or getprop(start,a_state) == attribute)
+ -- else
+ -- a = not attribute or getprop(start,a_state) == attribute
+ -- end
+ local a -- happens often so no assignment is faster
+ if attr then
+ if getattr(start,0) == attr and (not attribute or getprop(start,a_state) == attribute) then
+ a = true
+ end
+ elseif not attribute or getprop(start,a_state) == attribute then
+ a = true
end
if a then
for i=1,nofsteps do
@@ -3602,16 +3688,12 @@ local function featuresprocessor(head,font,attr)
local ok
head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i)
if ok then
- success = true
+ done = true
break
elseif not start then
-- don't ask why ... shouldn't happen
break
- -- elseif gpossing and zwnjruns and char == zwnj then
- -- discrun(start,d_run,font,attr,steps,nofsteps)
end
- -- elseif gpossing and zwnjruns and char == zwnj then
- -- discrun(start,d_run,font,attr,steps,nofsteps)
end
else
report_missing_coverage(dataset,sequence)
@@ -3626,22 +3708,16 @@ local function featuresprocessor(head,font,attr)
elseif char == false then
start = getnext(start)
elseif id == disc_code then
- -- see comment above
- local a = forcedisc or getsubtype(start) == discretionary_code or getattr(start,0) == attr
- if a then
- local ok
- if gpossing then
- start, ok = kernrun(start,k_run_multiple, font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
- elseif typ == "gsub_ligature" then
- start, ok = testrun(start,t_run_multiple,c_run_multiple,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
- else
- start, ok = comprun(start,c_run_multiple, font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
- end
- if ok then
- success = true
- end
+ local ok
+ if gpossing then
+ start, ok = kernrun(start,k_run_multiple, font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
+ elseif typ == "gsub_ligature" then
+ start, ok = testrun(start,t_run_multiple,c_run_multiple,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
else
- start = getnext(start)
+ start, ok = comprun(start,c_run_multiple, font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
+ end
+ if ok then
+ done = true
end
elseif id == math_code then
start = getnext(end_of_math(start))
@@ -3656,9 +3732,6 @@ local function featuresprocessor(head,font,attr)
end
end
- if success then
- done = true
- end
if trace_steps then -- ?
registerstep(head)
end
diff --git a/tex/context/base/mkiv/font-pre.mkiv b/tex/context/base/mkiv/font-pre.mkiv
index 881a577fb..24bb8de54 100644
--- a/tex/context/base/mkiv/font-pre.mkiv
+++ b/tex/context/base/mkiv/font-pre.mkiv
@@ -676,16 +676,27 @@
\definefontfeature[f:oldstyle] [onum=yes]
\definefontfeature[f:tabular] [tnum=yes]
\definefontfeature[f:superiors][sups=yes]
+\definefontfeature[f:fractions][frac=yes]
\definefontfeature[f:kern] [kern=yes]
\definefontfeature[f:kerns] [kern=yes]
\definealternativestyle [\v!smallcaps] [\setsmallcaps] [\setsmallcaps]
\definealternativestyle [\v!oldstyle] [\setoldstyle ] [\setoldstyle ]
+\definealternativestyle [\v!fractions] [\setfractions\resetbreakpoints] [\setfractions\resetbreakpoints]
\unexpanded\def\setsmallcaps{\doaddfeature{f:smallcaps}}
\unexpanded\def\setoldstyle {\doaddfeature{f:oldstyle}}
\unexpanded\def\settabular {\doaddfeature{f:tabular}}
\unexpanded\def\setsuperiors{\doaddfeature{f:superiors}}
+\unexpanded\def\setfractions{\doaddfeature{f:fractions}}
+
+% \unexpanded\def\frc#1#2%
+% {\dontleavehmode
+% \begingroup
+% \addff{frac}%
+% \resetbreakpoints
+% #1/#2%
+% \endgroup}
%D \macros
%D {tinyfont}
diff --git a/tex/context/base/mkiv/font-sel.lua b/tex/context/base/mkiv/font-sel.lua
index 1bfd41c70..455310e14 100644
--- a/tex/context/base/mkiv/font-sel.lua
+++ b/tex/context/base/mkiv/font-sel.lua
@@ -18,9 +18,9 @@ local formatters = string.formatters
local settings_to_array = utilities.parsers.settings_to_array
local settings_to_hash = utilities.parsers.settings_to_hash
local allocate = utilities.storage.allocate
-
+
local v_default = interfaces.variables.default
-
+
local implement = interfaces.implement
local fonts = fonts
@@ -49,7 +49,7 @@ local extras = selectfont.extras
local alternatives = selectfont.alternatives
local presets = selectfont.presets
local defaults = selectfont.defaults
-
+
local ctx_definefontsynonym = context.definefontsynonym
local ctx_resetfontfallback = context.resetfontfallback
local ctx_startfontclass = context.startfontclass
@@ -70,7 +70,6 @@ local report_selectfont = logs.reporter("selectfont")
local report_files = logs.reporter("selectfont","files")
local report_features = logs.reporter("selectfont","features")
local report_goodies = logs.reporter("selectfont","goodies")
-local report_alternatives = logs.reporter("selectfont","alternatives")
local report_typescript = logs.reporter("selectfont","typescripts")
defaults["rm"] = { features = { ["sc"] = "*,f:smallcaps" } }
@@ -943,4 +942,4 @@ implement {
name = "definefontfamilypreset",
actions = selectfont.definefontfamilypreset,
arguments = { "string", "string" }
-} \ No newline at end of file
+}
diff --git a/tex/context/base/mkiv/font-set.mkvi b/tex/context/base/mkiv/font-set.mkvi
index b29545ace..2c6d065d8 100644
--- a/tex/context/base/mkiv/font-set.mkvi
+++ b/tex/context/base/mkiv/font-set.mkvi
@@ -137,7 +137,7 @@
\unexpanded\def\font_preloads_fourth_stage
{\begingroup
%ifzeropt\fontcharwd\font\number`!\relax
- \setbox\scratchbox\hbox{c o n t e x t}%
+ \setbox\scratchbox\hpack{\tf c o n t e x t}%
\ifzeropt\wd\scratchbox
\writeline
\writestatus\m!fonts{!! No bodyfont has been defined and no defaults have been}%
diff --git a/tex/context/base/mkiv/font-sol.lua b/tex/context/base/mkiv/font-sol.lua
index 44c337dd5..82fc3dc40 100644
--- a/tex/context/base/mkiv/font-sol.lua
+++ b/tex/context/base/mkiv/font-sol.lua
@@ -65,8 +65,9 @@ local getattr = nuts.getattr
local getfont = nuts.getfont
local getsubtype = nuts.getsubtype
local getlist = nuts.getlist
+local getdir = nuts.getdir
+local getwidth = nuts.getwidth
-local setfield = nuts.setfield
local setattr = nuts.setattr
local setlink = nuts.setlink
local setnext = nuts.setnext
@@ -425,7 +426,7 @@ function splitters.split(head)
if start then
flush()
end
- rlmode = getfield(current,"dir")
+ rlmode = getdir(current)
else
if start then
flush()
@@ -757,8 +758,8 @@ function splitters.optimize(head)
for current in traverse_ids(hlist_code,tonut(head)) do
line = line + 1
local sign = getfield(current,"glue_sign")
- local dir = getfield(current,"dir")
- local width = getfield(current,"width")
+ local dir = getdir(current)
+ local width = getwidth(current)
local list = getlist(current)
if not encapsulate and getid(list) == glyph_code then
-- nasty .. we always assume a prev being there .. future luatex will always have a leftskip set
diff --git a/tex/context/base/mkiv/font-web.lua b/tex/context/base/mkiv/font-web.lua
index 8ea57f301..452a8f59b 100644
--- a/tex/context/base/mkiv/font-web.lua
+++ b/tex/context/base/mkiv/font-web.lua
@@ -12,6 +12,9 @@ if not modules then modules = { } end modules ['font-otr'] = {
-- and in a tex environment one can as well store the ttf/otf files in the tex tree. So,
-- eventually we might even remove this code when version 1 is obsolete.
+local ioopen = io.open
+local replacesuffix = file.replacesuffix
+
local readers = fonts and fonts.handlers.otf.readers
local streamreader = readers and readers.streamreader or utilities.files
@@ -44,10 +47,22 @@ local infotags = {
local report = logs.reporter("fonts","woff")
+local runner = sandbox.registerrunner {
+ name = "woff2otf",
+ method = "execute",
+ program = "woff2_decompress",
+ template = "%inputfile% %outputfile%",
+ reporter = report,
+ checkers = {
+ inputfile = "readable",
+ outputfile = "writable",
+ }
+}
+
local function woff2otf(inpname,outname,infoonly)
- local outname = outname or file.replacesuffix(inpname,"otf")
- local inp = io.open(inpname,"rb")
+ local outname = outname or replacesuffix(inpname,"otf")
+ local inp = ioopen(inpname,"rb")
if not inp then
report("invalid input file %a",inpname)
@@ -73,7 +88,12 @@ local function woff2otf(inpname,outname,infoonly)
if signature == "wOF2" then
inp:close()
if false then
- os.execute("woff2_decompress " .. inpname .. " " .. outname)
+ if runner then
+ runner {
+ inputfile = inpname,
+ outputfile = outname,
+ }
+ end
return outname, flavor
else
report("skipping version 2 file %a",inpname)
@@ -81,7 +101,7 @@ local function woff2otf(inpname,outname,infoonly)
end
end
- local out = io.open(outname,"wb")
+ local out = ioopen(outname,"wb")
if not out then
inp:close()
diff --git a/tex/context/base/mkiv/grph-con.lua b/tex/context/base/mkiv/grph-con.lua
index 380f56b14..65bb91631 100644
--- a/tex/context/base/mkiv/grph-con.lua
+++ b/tex/context/base/mkiv/grph-con.lua
@@ -16,7 +16,6 @@ local settings_to_array = utilities.parsers.settings_to_array
local settings_to_hash = utilities.parsers.settings_to_hash
local allocate = utilities.storage.allocate
local setmetatableindex = table.setmetatableindex
-local replacetemplate = utilities.templates.replace
local codeinjections = backends.codeinjections
local nodeinjections = backends.nodeinjections
@@ -34,7 +33,6 @@ local converters = figures.converters
local programs = figures.programs
local runprogram = programs.run
-local makeuptions = programs.makeoptions
do -- eps | ps
@@ -47,15 +45,16 @@ do -- eps | ps
local epsconverter = converters.eps
converters.ps = epsconverter
- local epstopdf = {
- resolutions = {
- [v_low] = "screen",
- [v_medium] = "ebook",
- [v_high] = "prepress",
- },
- command = os.type == "windows" and { "gswin64c", "gswin32c" } or "gs",
- -- -dProcessDSCComments=false
- argument = longtostring [[
+ local resolutions = {
+ [v_low] = "screen",
+ [v_medium] = "ebook",
+ [v_high] = "prepress",
+ }
+
+ local runner = sandbox.registerrunner {
+ name = "eps to pdf",
+ program = { windows = "gswin64c", unix = "gs" },
+ template = longtostring [[
-q
-sDEVICE=pdfwrite
-dNOPAUSE
@@ -70,10 +69,17 @@ do -- eps | ps
"%oldname%"
-c quit
]],
+ checkers = {
+ oldname = "readable",
+ newname = "writable",
+ presets = "string",
+ level = "string",
+ colorspace = "string",
+ },
}
- programs.epstopdf = epstopdf
- programs.gs = epstopdf
+ programs.epstopdf = { resolutions = epstopdf, runner = runner }
+ programs.gs = programs.epstopdf
local cleanups = { }
local cleaners = { }
@@ -85,9 +91,9 @@ do -- eps | ps
* P("%AI3_Cropmarks:") * quadruple
* P("%%CropBox:") * quadruple
/ function(b,h,m,c)
- return formatters["%%%%BoundingBox: %i %i %i %i\n%%%%HiResBoundingBox: %F %F %F %F\n%%%%CropBox: %F %F %F %F\n"](
- m[1],m[2],m[3],m[4],
- m[1],m[2],m[3],m[4],
+ return formatters["%%%%BoundingBox: %r %r %r %r\n%%%%HiResBoundingBox: %F %F %F %F\n%%%%CropBox: %F %F %F %F\n"](
+ m[1],m[2],m[3],m[4], -- rounded integer
+ m[1],m[2],m[3],m[4], -- real number
m[1],m[2],m[3],m[4]
)
end
@@ -108,8 +114,7 @@ do -- eps | ps
end
function epsconverter.pdf(oldname,newname,resolution,colorspace) -- the resolution interface might change
- local epstopdf = programs.epstopdf -- can be changed
- local presets = epstopdf.resolutions[resolution or "high"] or epstopdf.resolutions.high
+ local presets = resolutions[resolution or "high"] or resolutions.high
local level = codeinjections.getformatoption("pdf_level") or "1.3"
local tmpname = oldname
if not tmpname or tmpname == "" or not lfs.isfile(tmpname) then
@@ -124,13 +129,13 @@ do -- eps | ps
else
colorspace = nil
end
- runprogram(epstopdf.command, epstopdf.argument, {
+ runner {
newname = newname,
oldname = tmpname,
presets = presets,
level = tostring(level),
colorspace = colorspace,
- } )
+ }
if tmpname ~= oldname then
os.remove(tmpname)
end
@@ -144,29 +149,36 @@ do -- eps | ps
end
-do -- pdf
-
- local pdfconverter = converters.pdf
-
- -- programs.pdftoeps = {
- -- command = "pdftops",
- -- argument = [[-eps "%oldname%" "%newname%"]],
- -- }
- --
- -- pdfconverter.stripped = function(oldname,newname)
- -- local pdftoeps = programs.pdftoeps -- can be changed
- -- local epstopdf = programs.epstopdf -- can be changed
- -- local presets = epstopdf.resolutions[resolution or ""] or epstopdf.resolutions.high
- -- local level = codeinjections.getformatoption("pdf_level") or "1.3"
- -- local tmpname = newname .. ".tmp"
- -- runprogram(pdftoeps.command, pdftoeps.argument, { oldname = oldname, newname = tmpname, presets = presets, level = level })
- -- runprogram(epstopdf.command, epstopdf.argument, { oldname = tmpname, newname = newname, presets = presets, level = level })
- -- os.remove(tmpname)
- -- end
- --
- -- figures.registersuffix("stripped","pdf")
-
-end
+-- do -- pdf
+--
+-- local pdfconverter = converters.pdf
+--
+-- programs.pdftoeps = {
+-- runner = sandbox.registerrunner {
+-- name = "pdf to ps",
+-- command = "pdftops",
+-- template = [[-eps "%oldname%" "%newname%"]],
+-- checkers = {
+-- oldname = "readable",
+-- newname = "writable",
+-- }
+-- }
+-- }
+--
+-- pdfconverter.stripped = function(oldname,newname)
+-- local pdftoeps = programs.pdftoeps -- can be changed
+-- local epstopdf = programs.epstopdf -- can be changed
+-- local presets = epstopdf.resolutions[resolution or ""] or epstopdf.resolutions.high
+-- local level = codeinjections.getformatoption("pdf_level") or "1.3"
+-- local tmpname = newname .. ".tmp"
+-- pdftoeps.runner { oldname = oldname, newname = tmpname, presets = presets, level = level }
+-- epstopdf.runner { oldname = tmpname, newname = newname, presets = presets, level = level }
+-- os.remove(tmpname)
+-- end
+--
+-- figures.registersuffix("stripped","pdf")
+--
+-- end
do -- svg
@@ -177,34 +189,46 @@ do -- svg
-- arguments change again? Ok, it's weirder, with -A then it's a name only when
-- not . (current)
- programs.inkscape = {
- command = "inkscape",
- pdfargument = longtostring [[
+ local runner = sandbox.registerrunner {
+ name = "svg to something",
+ program = "inkscape",
+ template = longtostring [[
"%oldname%"
- --export-dpi=600
- --export-pdf="%newname%"
- ]],
- pngargument = longtostring [[
- "%oldname%"
- --export-dpi=600
- --export-png="%newname%"
+ --export-dpi=%resolution%
+ --export-%format%="%newname%"
]],
+ checkers = {
+ oldname = "readable",
+ newname = "writable",
+ format = "string",
+ resolution = "string",
+ },
+ defaults = {
+ format = "pdf",
+ resolution = "600",
+ }
+ }
+
+ programs.inkscape = {
+ runner = runner,
}
function svgconverter.pdf(oldname,newname)
- local inkscape = programs.inkscape -- can be changed
- runprogram(inkscape.command, inkscape.pdfargument, {
- newname = expandfilename(newname),
- oldname = expandfilename(oldname),
- } )
+ runner {
+ format = "pdf",
+ resolution = "600",
+ newname = expandfilename(newname),
+ oldname = expandfilename(oldname),
+ }
end
function svgconverter.png(oldname,newname)
- local inkscape = programs.inkscape
- runprogram(inkscape.command, inkscape.pngargument, {
- newname = expandfilename(newname),
- oldname = expandfilename(oldname),
- } )
+ runner {
+ format = "png",
+ resolution = "600",
+ newname = expandfilename(newname),
+ oldname = expandfilename(oldname),
+ }
end
svgconverter.default = svgconverter.pdf
@@ -280,81 +304,115 @@ do -- png | jpg | profiles
return rgbprofile, cmykprofile
end
- programs.pngtocmykpdf = {
- command = "gm",
- argument = [[convert -compress Zip -strip +profile "*" -profile "%rgbprofile%" -profile "%cmykprofile%" -sampling-factor 1x1 "%oldname%" "%newname%"]],
+ local checkers = {
+ oldname = "readable",
+ newname = "writable",
+ rgbprofile = "string",
+ cmykprofile = "string",
+ resolution = "string",
+ color = "string",
}
- programs.jpgtocmykpdf = {
- command = "gm",
- argument = [[convert -compress JPEG -strip +profile "*" -profile "%rgbprofile%" -profile "%cmykprofile%" -sampling-factor 1x1 "%oldname%" "%newname%"]],
+ local defaults = {
+ resolution = "600",
}
- programs.pngtograypdf = {
- command = "gm",
- argument = [[convert -colorspace gray -compress Zip -sampling-factor 1x1 "%oldname%" "%newname%"]],
+ local pngtocmykpdf = sandbox.registerrunner {
+ name = "png to cmyk pdf",
+ program = "gm",
+ template = [[convert -compress Zip -strip +profile "*" -profile "%rgbprofile%" -profile "%cmykprofile%" -sampling-factor 1x1 "%oldname%" "%newname%"]],
+ checkers = checkers,
+ defaults = defaults,
}
- programs.jpgtograypdf = {
- command = "gm",
- argument = [[convert -colorspace gray -compress Zip -sampling-factor 1x1 "%oldname%" "%newname%"]],
+ local jpgtocmykpdf = sandbox.registerrunner {
+ name = "jpg to cmyk pdf",
+ program = "gm",
+ template = [[convert -compress JPEG -strip +profile "*" -profile "%rgbprofile%" -profile "%cmykprofile%" -sampling-factor 1x1 "%oldname%" "%newname%"]],
+ checkers = checkers,
+ defaults = defaults,
}
+ local pngtograypdf = sandbox.registerrunner {
+ name = "png to gray pdf",
+ program = "gm",
+ template = [[convert -colorspace gray -compress Zip -sampling-factor 1x1 "%oldname%" "%newname%"]],
+ checkers = checkers,
+ defaults = defaults,
+ }
+
+ local jpgtograypdf = sandbox.registerrunner {
+ name = "jpg to gray pdf",
+ program = "gm",
+ template = [[convert -colorspace gray -compress Zip -sampling-factor 1x1 "%oldname%" "%newname%"]],
+ checkers = checkers,
+ defaults = defaults,
+ }
+
+ programs.pngtocmykpdf = { runner = pngtocmykpdf }
+ programs.jpgtocmykpdf = { runner = jpgtocmykpdf }
+ programs.pngtograypdf = { runner = pngtograypdf }
+ programs.jpgtograypdf = { runner = jpgtograypdf }
+
pngconverters["cmyk.pdf"] = function(oldname,newname,resolution)
local rgbprofile, cmykprofile = profiles()
- runprogram(programs.pngtocmykpdf.command, programs.pngtocmykpdf.argument, {
- -- runprogram(programs.pngtocmykpdf, {
- rgbprofile = rgbprofile,
- cmykprofile = cmykprofile,
+ pngtocmykpdf {
oldname = oldname,
newname = newname,
- } )
+ rgbprofile = rgbprofile,
+ cmykprofile = cmykprofile,
+ resolution = resolution,
+ }
end
pngconverters["gray.pdf"] = function(oldname,newname,resolution)
- runprogram(programs.pngtograypdf.command, programs.pngtograypdf.argument, {
- -- runprogram(programs.pngtograypdf, {
- oldname = oldname,
- newname = newname,
- } )
+ pngtograypdf {
+ oldname = oldname,
+ newname = newname,
+ resolution = resolution,
+ }
end
jpgconverters["cmyk.pdf"] = function(oldname,newname,resolution)
local rgbprofile, cmykprofile = profiles()
- runprogram(programs.jpgtocmykpdf.command, programs.jpgtocmykpdf.argument, {
- -- runprogram(programs.jpgtocmykpdf, {
- rgbprofile = rgbprofile,
- cmykprofile = cmykprofile,
+ jpgtocmykpdf {
oldname = oldname,
newname = newname,
- } )
+ rgbprofile = rgbprofile,
+ cmykprofile = cmykprofile,
+ resolution = resolution,
+ }
end
jpgconverters["gray.pdf"] = function(oldname,newname,resolution)
- runprogram(programs.jpgtograypdf.command, programs.jpgtograypdf.argument, {
- -- runprogram(programs.jpgtograypdf, {
- oldname = oldname,
- newname = newname,
- } )
+ jpgtograypdf {
+ oldname = oldname,
+ newname = newname,
+ resolution = resolution,
+ }
end
-- recolor
- programs.recolor = {
- command = "gm",
- argument = [[convert -recolor "%color%" "%oldname%" "%newname%"]],
+ local recolorpng = sandbox.registerrunner {
+ name = "recolor png",
+ program = "gm",
+ template = [[convert -recolor "%color%" "%oldname%" "%newname%"]],
+ checkers = checkers,
+ defaults = defaults,
}
+ -- this is now built in so not really needed any more
+
+ programs.recolor = { runner = recolorpng }
+
pngconverters["recolor.png"] = function(oldname,newname,resolution,arguments)
- runprogram (
- programs.recolor.command,
- programs.recolor.argument,
- {
- oldname = oldname,
- newname = newname,
- color = arguments or ".5 0 0 .7 0 0 .9 0 0",
- }
- )
+ recolorpng {
+ oldname = oldname,
+ newname = newname,
+ resolution = resolution,
+ color = arguments or ".5 0 0 .7 0 0 .9 0 0",
+ }
end
end
diff --git a/tex/context/base/mkiv/grph-fil.lua b/tex/context/base/mkiv/grph-fil.lua
index e774d097e..3c069da37 100644
--- a/tex/context/base/mkiv/grph-fil.lua
+++ b/tex/context/base/mkiv/grph-fil.lua
@@ -42,6 +42,16 @@ end
job.register('job.files.collected', tobesaved, initializer)
+local runner = sandbox.registerrunner {
+ name = "hashed context run",
+ program = "context",
+ template = [[%options% "%filename%"]],
+ checkers = {
+ options = "string",
+ filename = "readable",
+ }
+}
+
function jobfiles.run(name,action)
local usedname = addsuffix(name,inputsuffix) -- we assume tex if not set
local oldchecksum = collected[usedname]
@@ -55,7 +65,10 @@ function jobfiles.run(name,action)
if ta == "function" then
action(name)
elseif ta == "string" and action ~= "" then
+ -- can be anything but we assume it gets checked by the sandbox
os.execute(action)
+ elseif ta == "table" then
+ runner(action)
else
report_run("processing file, no action given for processing %a",name)
end
@@ -79,7 +92,7 @@ function jobfiles.context(name,options)
else
local result = replacesuffix(name,resultsuffix)
if not done[result] then
- jobfiles.run(name,"context ".. (options or "") .. " " .. name)
+ jobfiles.run(name, { options = options, filename = name })
done[result] = true
end
return result
diff --git a/tex/context/base/mkiv/grph-inc.lua b/tex/context/base/mkiv/grph-inc.lua
index 901d31827..b5e74b4c1 100644
--- a/tex/context/base/mkiv/grph-inc.lua
+++ b/tex/context/base/mkiv/grph-inc.lua
@@ -47,7 +47,6 @@ local concat, insert, remove = table.concat, table.insert, table.remove
local todimen = string.todimen
local collapsepath = file.collapsepath
local formatters = string.formatters
-local expandfilename = dir.expandname
local formatcolumns = utilities.formatters.formatcolumns
local P, R, S, Cc, C, Cs, Ct, lpegmatch = lpeg.P, lpeg.R, lpeg.S, lpeg.Cc, lpeg.C, lpeg.Cs, lpeg.Ct, lpeg.match
@@ -97,16 +96,12 @@ end
local report_inclusion = logs.reporter("graphics","inclusion")
local report_figures = logs.reporter("system","graphics")
local report_figure = logs.reporter("used graphic")
-local report_status = logs.reporter("graphics","status")
local report_newline = logs.newline
local f_hash_part = formatters["%s->%s->%s->%s"]
local f_hash_full = formatters["%s->%s->%s->%s->%s->%s->%s->%s"]
local v_yes = variables.yes
-local v_low = variables.low
-local v_medium = variables.medium
-local v_high = variables.high
local v_global = variables["global"]
local v_local = variables["local"]
local v_default = variables.default
@@ -1636,13 +1631,15 @@ includers.cld = includers.nongeneric
setmetatableindex(converters,"table")
+-- We keep this helper because it has been around for a while and therefore it can
+-- be a depedency in an existing workflow.
+
function programs.makeoptions(options)
local to = type(options)
return (to == "table" and concat(options," ")) or (to == "string" and options) or ""
end
function programs.run(binary,argument,variables)
- -- move this check to the runner code
local found = nil
if type(binary) == "table" then
for i=1,#binary do
diff --git a/tex/context/base/mkiv/grph-inc.mkiv b/tex/context/base/mkiv/grph-inc.mkiv
index 90453b8ed..881bf9713 100644
--- a/tex/context/base/mkiv/grph-inc.mkiv
+++ b/tex/context/base/mkiv/grph-inc.mkiv
@@ -316,7 +316,7 @@
\edef\p_reference{\externalfigureparameter\c!reference}%
%
\dostarttagged\t!image\empty
- \clf_figure_push
+ \clf_figure_push {
name {\p_grph_include_name}%
label {\ifx\p_label\empty\p_grph_include_label\else\p_label\fi}%
page {\externalfigureparameter\c!page}%
@@ -343,7 +343,7 @@
\ifx\p_height\empty \else
height \dimexpr\p_height\relax
\fi
- \relax
+ }%\relax
\clf_figure_identify
\relax
\ifconditional\c_grph_include_test_only
diff --git a/tex/context/base/mkiv/grph-rul.lua b/tex/context/base/mkiv/grph-rul.lua
index 4ac73b6ae..e3d1d8963 100644
--- a/tex/context/base/mkiv/grph-rul.lua
+++ b/tex/context/base/mkiv/grph-rul.lua
@@ -175,6 +175,7 @@ interfaces.implement {
{ "name", "string" },
} } ,
actions = function(t)
+ -- no nuts !
local rule = userrule(t)
local ma = getattribute(a_colormodel) or 1
local ca = getattribute(a_color)
diff --git a/tex/context/base/mkiv/l-lpeg.lua b/tex/context/base/mkiv/l-lpeg.lua
index 959ca553e..877dae644 100644
--- a/tex/context/base/mkiv/l-lpeg.lua
+++ b/tex/context/base/mkiv/l-lpeg.lua
@@ -839,28 +839,48 @@ end
local p_false = P(false)
local p_true = P(true)
-local function make(t)
- local function making(t)
- local p = p_false
- local keys = sortedkeys(t)
- for i=1,#keys do
- local k = keys[i]
- if k ~= "" then
- local v = t[k]
- if v == true then
- p = p + P(k) * p_true
- elseif v == false then
- -- can't happen
- else
- p = p + P(k) * making(v)
- end
- end
- end
- if t[""] then
- p = p + p_true
- end
- return p
- end
+-- local function making(t)
+-- local p = p_false
+-- local keys = sortedkeys(t)
+-- for i=1,#keys do
+-- local k = keys[i]
+-- if k ~= "" then
+-- local v = t[k]
+-- if v == true then
+-- p = p + P(k) * p_true
+-- elseif v == false then
+-- -- can't happen
+-- else
+-- p = p + P(k) * making(v)
+-- end
+-- end
+-- end
+-- if t[""] then
+-- p = p + p_true
+-- end
+-- return p
+-- end
+
+-- local function make(t)
+-- local p = p_false
+-- local keys = sortedkeys(t)
+-- for i=1,#keys do
+-- local k = keys[i]
+-- if k ~= "" then
+-- local v = t[k]
+-- if v == true then
+-- p = p + P(k) * p_true
+-- elseif v == false then
+-- -- can't happen
+-- else
+-- p = p + P(k) * making(v)
+-- end
+-- end
+-- end
+-- return p
+-- end
+
+local function make(t,rest)
local p = p_false
local keys = sortedkeys(t)
for i=1,#keys do
@@ -872,10 +892,13 @@ local function make(t)
elseif v == false then
-- can't happen
else
- p = p + P(k) * making(v)
+ p = p + P(k) * make(v,v[""])
end
end
end
+ if rest then
+ p = p + p_true
+ end
return p
end
@@ -990,21 +1013,21 @@ end
-- local t = { "a", "abc", "ac", "abe", "abxyz", "xy", "bef","aa" }
-- local p = lpeg.Cs((lpeg.utfchartabletopattern(t)/string.upper + 1)^1)
--- inspect(lpegmatch(p,"a"))
--- inspect(lpegmatch(p,"aa"))
--- inspect(lpegmatch(p,"aaaa"))
--- inspect(lpegmatch(p,"ac"))
--- inspect(lpegmatch(p,"bc"))
--- inspect(lpegmatch(p,"zzbczz"))
--- inspect(lpegmatch(p,"zzabezz"))
--- inspect(lpegmatch(p,"ab"))
--- inspect(lpegmatch(p,"abc"))
--- inspect(lpegmatch(p,"abe"))
--- inspect(lpegmatch(p,"xa"))
--- inspect(lpegmatch(p,"bx"))
--- inspect(lpegmatch(p,"bax"))
--- inspect(lpegmatch(p,"abxyz"))
--- inspect(lpegmatch(p,"foobarbefcrap"))
+-- inspect(lpegmatch(p,"a")=="A")
+-- inspect(lpegmatch(p,"aa")=="AA")
+-- inspect(lpegmatch(p,"aaaa")=="AAAA")
+-- inspect(lpegmatch(p,"ac")=="AC")
+-- inspect(lpegmatch(p,"bc")=="bc")
+-- inspect(lpegmatch(p,"zzbczz")=="zzbczz")
+-- inspect(lpegmatch(p,"zzabezz")=="zzABEzz")
+-- inspect(lpegmatch(p,"ab")=="Ab")
+-- inspect(lpegmatch(p,"abc")=="ABC")
+-- inspect(lpegmatch(p,"abe")=="ABE")
+-- inspect(lpegmatch(p,"xa")=="xA")
+-- inspect(lpegmatch(p,"bx")=="bx")
+-- inspect(lpegmatch(p,"bax")=="bAx")
+-- inspect(lpegmatch(p,"abxyz")=="ABXYZ")
+-- inspect(lpegmatch(p,"foobarbefcrap")=="foobArBEFcrAp")
-- local t = { ["^"] = 1, ["^^"] = 2, ["^^^"] = 3, ["^^^^"] = 4 }
-- local p = lpeg.Cs((lpeg.utfchartabletopattern(t)/t + 1)^1)
diff --git a/tex/context/base/mkiv/l-lua.lua b/tex/context/base/mkiv/l-lua.lua
index 357153836..adc2c97a8 100644
--- a/tex/context/base/mkiv/l-lua.lua
+++ b/tex/context/base/mkiv/l-lua.lua
@@ -188,7 +188,7 @@ if lua then
lua.mask = load([[τεχ = 1]]) and "utf" or "ascii"
end
-local flush = io.flush
+local flush = io.flush
if flush then
@@ -199,3 +199,85 @@ if flush then
end
+-- new
+
+if ffi and ffi.number then
+ -- already loaded
+else
+ local okay
+
+ okay, ffi = pcall(require,"ffi")
+
+ if not ffi then
+ -- an old version
+ elseif ffi.os == "" or ffi.arch == "" then
+ -- no ffi support
+ ffi = nil
+ elseif ffi.number then
+ -- luatex
+ else
+ -- luajittex
+ ffi.number = tonumber
+ end
+end
+
+-- done differently in context
+--
+-- if ffi then
+-- local load = ffi.load
+-- local select = select
+-- local type = type
+-- local next = next
+-- local sort = table.sort
+-- local gmatch = string.gmatch
+-- local okay = true
+-- local control = { }
+-- function ffi.load(name,...)
+-- if okay == true or okay[name] then
+-- return load(name,...)
+-- else
+-- return nil
+-- end
+-- end
+-- function control.permit(...)
+-- if okay == true then
+-- okay = { }
+-- end
+-- for i=1,select("#",...) do
+-- local n = select(i,...)
+-- local t = type(n)
+-- if t == "table" then
+-- for i=1,#n do
+-- control.permit(n[i])
+-- end
+-- elseif t == "string" then
+-- for s in gmatch(n,"[^,%s]+") do
+-- okay[n] = true
+-- end
+-- end
+-- end
+-- end
+-- function control.freeze(none)
+-- control.permit = function() end
+-- control.freeze = function() end
+-- if none then
+-- okay = { }
+-- end
+-- end
+-- function control.permitted(name)
+-- if okay == true then
+-- return true
+-- elseif type(name) == "string" then
+-- return okay[name] or false
+-- else
+-- -- no helpers yet
+-- local t = { }
+-- for k, v in next, okay do
+-- t[#t+1] = k
+-- end
+-- sort(t)
+-- return t
+-- end
+-- end
+-- ffi.control = control
+-- end
diff --git a/tex/context/base/mkiv/l-os.lua b/tex/context/base/mkiv/l-os.lua
index 0a86ea6d6..5108faeef 100644
--- a/tex/context/base/mkiv/l-os.lua
+++ b/tex/context/base/mkiv/l-os.lua
@@ -119,7 +119,7 @@ end
local execute = os.execute
local iopopen = io.popen
-function os.resultof(command)
+local function resultof(command)
local handle = iopopen(command,"r") -- already has flush
if handle then
local result = handle:read("*all") or ""
@@ -130,9 +130,15 @@ function os.resultof(command)
end
end
+os.resultof = resultof
+
+function os.pipeto(command)
+ return iopopen(command,"w") -- already has flush
+end
+
if not io.fileseparator then
if find(os.getenv("PATH"),";",1,true) then
- io.fileseparator, io.pathseparator, os.type = "\\", ";", os.type or "mswin"
+ io.fileseparator, io.pathseparator, os.type = "\\", ";", os.type or "windows"
else
io.fileseparator, io.pathseparator, os.type = "/" , ":", os.type or "unix"
end
@@ -203,17 +209,17 @@ end })
local name, platform = os.name or "linux", os.getenv("MTX_PLATFORM") or ""
-local function guess()
- local architecture = os.resultof("uname -m") or ""
- if architecture ~= "" then
- return architecture
- end
- architecture = os.getenv("HOSTTYPE") or ""
- if architecture ~= "" then
- return architecture
- end
- return os.resultof("echo $HOSTTYPE") or ""
-end
+-- local function guess()
+-- local architecture = resultof("uname -m") or ""
+-- if architecture ~= "" then
+-- return architecture
+-- end
+-- architecture = os.getenv("HOSTTYPE") or ""
+-- if architecture ~= "" then
+-- return architecture
+-- end
+-- return resultof("echo $HOSTTYPE") or ""
+-- end
-- os.bits = 32 | 64
@@ -245,7 +251,7 @@ elseif name == "linux" then
function resolvers.platform(t,k)
-- we sometimes have HOSTTYPE set so let's check that first
- local platform, architecture = "", os.getenv("HOSTTYPE") or os.resultof("uname -m") or ""
+ local platform, architecture = "", os.getenv("HOSTTYPE") or resultof("uname -m") or ""
if find(architecture,"x86_64",1,true) then
platform = "linux-64"
elseif find(architecture,"ppc",1,true) then
@@ -273,9 +279,9 @@ elseif name == "macosx" then
function resolvers.platform(t,k)
-- local platform, architecture = "", os.getenv("HOSTTYPE") or ""
-- if architecture == "" then
- -- architecture = os.resultof("echo $HOSTTYPE") or ""
+ -- architecture = resultof("echo $HOSTTYPE") or ""
-- end
- local platform, architecture = "", os.resultof("echo $HOSTTYPE") or ""
+ local platform, architecture = "", resultof("echo $HOSTTYPE") or ""
if architecture == "" then
-- print("\nI have no clue what kind of OSX you're running so let's assume an 32 bit intel.\n")
platform = "osx-intel"
@@ -294,7 +300,7 @@ elseif name == "macosx" then
elseif name == "sunos" then
function resolvers.platform(t,k)
- local platform, architecture = "", os.resultof("uname -m") or ""
+ local platform, architecture = "", resultof("uname -m") or ""
if find(architecture,"sparc",1,true) then
platform = "solaris-sparc"
else -- if architecture == 'i86pc'
@@ -308,7 +314,7 @@ elseif name == "sunos" then
elseif name == "freebsd" then
function resolvers.platform(t,k)
- local platform, architecture = "", os.resultof("uname -m") or ""
+ local platform, architecture = "", resultof("uname -m") or ""
if find(architecture,"amd64",1,true) then
platform = "freebsd-amd64"
else
@@ -323,7 +329,7 @@ elseif name == "kfreebsd" then
function resolvers.platform(t,k)
-- we sometimes have HOSTTYPE set so let's check that first
- local platform, architecture = "", os.getenv("HOSTTYPE") or os.resultof("uname -m") or ""
+ local platform, architecture = "", os.getenv("HOSTTYPE") or resultof("uname -m") or ""
if find(architecture,"x86_64",1,true) then
platform = "kfreebsd-amd64"
else
diff --git a/tex/context/base/mkiv/l-sandbox.lua b/tex/context/base/mkiv/l-sandbox.lua
index f7901379c..a95e70395 100644
--- a/tex/context/base/mkiv/l-sandbox.lua
+++ b/tex/context/base/mkiv/l-sandbox.lua
@@ -8,8 +8,8 @@ if not modules then modules = { } end modules ['l-sandbox'] = {
-- We use string instead of function variables, so 'io.open' instead of io.open. That
-- way we can still intercept repetetive overloads. One complication is that when we use
--- sandboxed function sin helpers in the sanbox checkers, we can get a recursion loop
--- so for that vreason we need to keep originals around till we enable the sandbox.
+-- sandboxed functions in helpers in the sanbox checkers, we can get a recursion loop
+-- so for that reason we need to keep originals around till we enable the sandbox.
-- if sandbox then return end
@@ -23,6 +23,8 @@ local format = string.format -- no formatters yet
local concat = table.concat
local sort = table.sort
local gmatch = string.gmatch
+local gsub = string.gsub
+local requiem = require
sandbox = { }
local sandboxed = false
@@ -34,6 +36,7 @@ local originals = { }
local comments = { }
local trace = false
local logger = false
+local blocked = { }
-- this comes real early, so that we can still alias
@@ -139,29 +142,62 @@ function sandbox.overload(func,overload,comment)
return func
end
-function sandbox.initializer(f)
- if not sandboxed then
- initializers[#initializers+1] = f
+local function whatever(specification,what,target)
+ if type(specification) ~= "table" then
+ report("%s needs a specification",what)
+ elseif type(specification.category) ~= "string" or type(specification.action) ~= "function" then
+ report("%s needs a category and action",what)
+ elseif not sandboxed then
+ target[#target+1] = specification
elseif trace then
- report("already enabled, discarding initializer")
+ report("already enabled, discarding %s",what)
end
end
-function sandbox.finalizer(f)
- if not sandboxed then
- finalizers[#finalizers+1] = f
- elseif trace then
- report("already enabled, discarding finalizer")
+function sandbox.initializer(specification)
+ whatever(specification,"initializer",initializers)
+end
+
+function sandbox.finalizer(specification)
+ whatever(specification,"finalizer",finalizers)
+end
+
+function require(name)
+ local n = gsub(name,"^.*[\\/]","")
+ local n = gsub(n,"[%.].*$","")
+ local b = blocked[n]
+ if b then
+ if trace then
+ report("using blocked: %s",n)
+ end
+ return b
+ else
+ if trace then
+ report("requiring: %s",name)
+ end
+ return requiem(name)
+ end
+end
+
+function blockrequire(name,lib)
+ if trace then
+ report("preventing reload of: %s",name)
end
+ blocked[name] = lib or _G[name]
+end
+
+if TEXENGINE == "luajittex" or not ffi then
+ local ok
+ ok, ffi = pcall(require,"ffi")
end
function sandbox.enable()
if not sandboxed then
for i=1,#initializers do
- initializers[i]()
+ initializers[i].action()
end
for i=1,#finalizers do
- finalizers[i]()
+ finalizers[i].action()
end
local nnot = 0
local nyes = 0
@@ -189,22 +225,48 @@ function sandbox.enable()
end
if #cyes > 0 then
sort(cyes)
- report(" overloaded known : %s",concat(cyes," | "))
+ report("overloaded known: %s",concat(cyes," | "))
end
if nyes > 0 then
- report(" overloaded unknown : %s",nyes)
+ report("overloaded unknown: %s",nyes)
end
if #cnot > 0 then
sort(cnot)
- report("not overloaded known : %s",concat(cnot," | "))
+ report("not overloaded known: %s",concat(cnot," | "))
end
if nnot > 0 then
- report("not overloaded unknown : %s",nnot)
+ report("not overloaded unknown: %s",nnot)
end
if #skip > 0 then
sort(skip)
- report("not overloaded redefined : %s",concat(skip," | "))
+ report("not overloaded redefined: %s",concat(skip," | "))
end
+ --
+ -- if ffi then
+ -- report("disabling ffi")
+ -- -- for k, v in next, ffi do
+ -- -- if k ~= "gc" then
+ -- -- local t = type(v)
+ -- -- if t == "function" then
+ -- -- ffi[k] = function() report("accessing ffi.%s",k) end
+ -- -- elseif t == "number" then
+ -- -- ffi[k] = 0
+ -- -- elseif t == "string" then
+ -- -- ffi[k] = ""
+ -- -- elseif t == "table" then
+ -- -- ffi[k] = { }
+ -- -- else
+ -- -- ffi[k] = false
+ -- -- end
+ -- -- end
+ -- -- end
+ -- for k, v in next, ffi do
+ -- if k ~= "gc" then
+ -- ffi[k] = nil
+ -- end
+ -- end
+ -- end
+ --
initializers = nil
finalizers = nil
originals = nil
@@ -212,6 +274,13 @@ function sandbox.enable()
end
end
+blockrequire("lfs",lfs)
+blockrequire("io",io)
+blockrequire("os",os)
+blockrequire("ffi",ffi)
+
+-- require = register(require,"require")
+
-- we sandbox some of the built-in functions now:
-- todo: require
diff --git a/tex/context/base/mkiv/l-unicode.lua b/tex/context/base/mkiv/l-unicode.lua
index 3dec80013..b913d0cfc 100644
--- a/tex/context/base/mkiv/l-unicode.lua
+++ b/tex/context/base/mkiv/l-unicode.lua
@@ -1270,3 +1270,35 @@ function utf.chrlen(u) -- u is number
(u < 0xFC and 5) or
(u < 0xFE and 6) or 0
end
+
+-- hashing saves a little but not that much in practice
+--
+-- local utf32 = table.setmetatableindex(function(t,k) local v = toutf32(k) t[k] = v return v end)
+
+local extract = bit32.extract
+local char = string.char
+
+function unicode.toutf32string(n)
+ if n <= 0xFF then
+ return
+ char(n) ..
+ "\000\000\000"
+ elseif n <= 0xFFFF then
+ return
+ char(extract(n, 0,8)) ..
+ char(extract(n, 8,8)) ..
+ "\000\000"
+ elseif n <= 0xFFFFFF then
+ return
+ char(extract(n, 0,8)) ..
+ char(extract(n, 8,8)) ..
+ char(extract(n,16,8)) ..
+ "\000"
+ else
+ return
+ char(extract(n, 0,8)) ..
+ char(extract(n, 8,8)) ..
+ char(extract(n,16,8)) ..
+ char(extract(n,24,8))
+ end
+end
diff --git a/tex/context/base/mkiv/lang-dis.lua b/tex/context/base/mkiv/lang-dis.lua
index e6ea180b0..34d7ec000 100644
--- a/tex/context/base/mkiv/lang-dis.lua
+++ b/tex/context/base/mkiv/lang-dis.lua
@@ -13,6 +13,9 @@ local nodes = nodes
local tasks = nodes.tasks
local nuts = nodes.nuts
+local enableaction = tasks.enableaction
+local setaction = tasks.setaction
+
local tonode = nuts.tonode
local tonut = nuts.tonut
@@ -29,12 +32,17 @@ local getchar = nuts.getchar
local setchar = nuts.setchar
local getdisc = nuts.getdisc
local setdisc = nuts.setdisc
+local getlang = nuts.setlang
+local getboth = nuts.getboth
+local setlist = nuts.setlist
+local setlink = nuts.setlink
local isglyph = nuts.isglyph
local copy_node = nuts.copy
local remove_node = nuts.remove
local traverse_id = nuts.traverse_id
local flush_list = nuts.flush_list
+local flush_node = nuts.flush_node
local nodecodes = nodes.nodecodes
local disccodes = nodes.disccodes
@@ -83,7 +91,7 @@ local expanders = {
-- todo: take existing penalty
setdisc(d,pre,post,replace,explicit_code,tex.exhyphenpenalty)
else
- setfield(d,"subtype",explicit_code)
+ setsubtype(d,explicit_code)
end
return template
end,
@@ -141,7 +149,7 @@ local expanders = {
end
end
if template then
- local language = template and getfield(template,"lang")
+ local language = template and getlang(template)
local data = getlanguagedata(language)
local prechar = data.prehyphenchar
local postchar = data.posthyphenchar
@@ -214,7 +222,7 @@ function languages.showdiscretionaries(v)
setattribute(a_visualize,unsetvalue)
else -- also nil
if not enabled then
- nodes.tasks.enableaction("processors","languages.visualizediscretionaries")
+ enableaction("processors","languages.visualizediscretionaries")
enabled = true
end
setattribute(a_visualize,1)
@@ -237,3 +245,71 @@ function languages.serializediscretionary(d) -- will move to tracer
)
end
+-- --
+
+local wiped = 0
+
+local function wipe(head,delayed)
+ local p, n = getboth(delayed)
+ local _, _, h, _, _, t = getdisc(delayed,true)
+ if p or n then
+ if h then
+ setlink(p,h)
+ setlink(t,n)
+ setfield(delayed,"replace")
+ else
+ setlink(p,n)
+ end
+ end
+ if head == delayed then
+ head = h
+ end
+ wiped = wiped + 1
+ flush_node(delayed)
+ return head
+end
+
+function languages.flatten(head)
+ local nuthead = tonut(head)
+ local delayed = nil
+ for d in traverse_id(disc_code,nuthead) do
+ if delayed then
+ nuthead = wipe(nuthead,delayed)
+ end
+ delayed = d
+ end
+ if delayed then
+ return tonode(wipe(nuthead,delayed)), true
+ else
+ return head, false
+ end
+end
+
+function languages.nofflattened()
+ return wiped -- handy for testing
+end
+
+-- experiment
+
+local flatten = languages.flatten
+local getlist = nodes.getlist
+
+function nodes.handlers.flattenline(head)
+ local list = getlist(head)
+ if list then
+ flatten(list)
+ end
+ return head
+end
+
+function nodes.handlers.flatten(head,where)
+ if head and (where == "box" or where == "adjusted_hbox") then
+ return flatten(head)
+ end
+ return true
+end
+
+directives.register("hyphenator.flatten",function(v)
+ setaction("processors","nodes.handlers.flatten",v)
+ setaction("contributers","nodes.handlers.flattenline",v)
+end)
diff --git a/tex/context/base/mkiv/lang-hyp.lua b/tex/context/base/mkiv/lang-hyp.lua
index b80bb003b..50132bfe1 100644
--- a/tex/context/base/mkiv/lang-hyp.lua
+++ b/tex/context/base/mkiv/lang-hyp.lua
@@ -78,6 +78,8 @@ if not modules then modules = { } end modules ['lang-hyp'] = {
-- ins : when hyphenationbounds 2 or 3
-- adjust : when hyphenationbounds 2 or 3
+-- todo: maybe subtypes (because they have subtle meanings in the line breaking)
+
local type, rawset, tonumber, next = type, rawset, tonumber, next
local P, R, S, Cg, Cf, Ct, Cc, C, Carg, Cs = lpeg.P, lpeg.R, lpeg.S, lpeg.Cg, lpeg.Cf, lpeg.Ct, lpeg.Cc, lpeg.C, lpeg.Carg, lpeg.Cs
@@ -652,9 +654,11 @@ if context then
local getprev = nuts.getprev
local getsubtype = nuts.getsubtype
local getlist = nuts.getlist
+ local getlang = nuts.getlang
+ local getattrlist = nuts.getattrlist
+ local setattrlist = nuts.setattrlist
local isglyph = nuts.isglyph
- local setfield = nuts.setfield
local setchar = nuts.setchar
local setdisc = nuts.setdisc
@@ -993,6 +997,8 @@ if context then
[nodecodes.math] = true,
}
+ -- local gf = getfield local gt = setmetatableindex("number") getfield = function(n,f) gt[f] = gt[f] + 1 return gf(n,f) end languages.GETFIELD = gt
+
function traditional.hyphenate(head)
local first = tonut(head)
@@ -1045,7 +1051,7 @@ if context then
local function insertpenalty()
local p = new_penalty(interwordpenalty)
- setfield(p,"attr",getfield(last,"attr"))
+ setattrlist(p,last)
if trace_visualize then
nuts.setvisual(p,"penalty")
end
@@ -1233,7 +1239,7 @@ if context then
local current = start
- local attributes = getfield(start,"attr") -- todo: just copy the last disc .. faster
+ local attrnode = start -- will be different, just the first char
for i=1,rsize do
local r = result[i]
@@ -1248,8 +1254,8 @@ if context then
post = serialize(true,leftchar)
end
setdisc(disc,pre,post,nil,discretionary_code,hyphenpenalty)
- if attributes then
- setfield(disc,"attr",attributes)
+ if attrnode then
+ setattrlist(disc,attrnode)
end
-- could be a replace as well
insert_before(first,current,disc)
@@ -1282,8 +1288,8 @@ if context then
end
end
setdisc(disc,pre,post,replace,discretionary_code,hyphenpenalty)
- if attributes then
- setfield(disc,"attr",attributes)
+ if attrnode then
+ setattrlist(disc,attrnode)
end
insert_before(first,current,disc)
else
@@ -1303,7 +1309,7 @@ if context then
end
- local function inject(leftchar,rightchar,code,attributes)
+ local function inject(leftchar,rightchar,code,attrnode)
if first ~= current then
local disc = new_disc()
first, current, glyph = remove_node(first,current)
@@ -1322,8 +1328,8 @@ if context then
pre = copy_node(glyph)
setchar(pre,rightchar and rightchar > 0 and rightchar or code)
setdisc(disc,pre,post,replace,discretionary_code,hyphenpenalty)
- if attributes then
- setfield(disc,"attr",attributes)
+ if attrnode then
+ setattrlist(disc,attrnode)
end
end
return current
@@ -1343,9 +1349,10 @@ if context then
while current and current ~= last do -- and current
local code, id = isglyph(current)
if code then
- local lang = getfield(current,"lang")
+ local lang = getlang(current)
if lang ~= language then
if dictionary and size > charmin and leftmin + rightmin <= size then
+ -- only german has many words starting with an uppercase character
if categories[word[1]] == "lu" and getfield(start,"uchyph") < 0 then
-- skip
else
@@ -1411,9 +1418,9 @@ if context then
-- maybe also a strict mode here: no hyphenation before hyphenchars and skip
-- the next set (but then, strict is an option)
if code == exhyphenchar then
- current = inject(leftexchar,rightexchar,code,getfield(current,"attr"))
+ current = inject(leftexchar,rightexchar,code,current)
elseif hyphenchars and hyphenchars[code] then
- current = inject(leftchar,rightchar,code,getfield(current,"attr"))
+ current = inject(leftchar,rightchar,code,current)
end
end
else
@@ -1557,11 +1564,13 @@ if context then
local getcount = tex.getcount
hyphenators.methods = methods
- hyphenators.optimize = false
+ local optimize = false
+
+ directives.register("hyphenator.optimize", function(v) optimize = v end)
function hyphenators.handler(head,groupcode)
if usedmethod then
- if groupcode == "hbox" and hyphenators.optimize then
+ if optimize and (groupcode == "hbox" or groupcode == "adjusted_hbox") then
if getcount("hyphenstate") > 0 then
forced = false
return usedmethod(head)
diff --git a/tex/context/base/mkiv/lang-rep.lua b/tex/context/base/mkiv/lang-rep.lua
index 2e998b7fb..6fde353f7 100644
--- a/tex/context/base/mkiv/lang-rep.lua
+++ b/tex/context/base/mkiv/lang-rep.lua
@@ -52,11 +52,13 @@ local getchar = nuts.getchar
local isglyph = nuts.isglyph
local setfield = nuts.setfield
+local getfield = nuts.getfield
local setattr = nuts.setattr
local setlink = nuts.setlink
local setnext = nuts.setnext
local setprev = nuts.setprev
local setchar = nuts.setchar
+local setattrlist = nuts.setattrlist
local insert_node_before = nuts.insert_before
local remove_node = nuts.remove
@@ -70,6 +72,8 @@ local new_disc = nodepool.disc
local texsetattribute = tex.setattribute
local unsetvalue = attributes.unsetvalue
+local enableaction = nodes.tasks.enableaction
+
local v_reset = interfaces.variables.reset
local implement = interfaces.implement
@@ -222,34 +226,35 @@ function replacements.handler(head)
local i = 1
while i <= newlength do
local codes = newcodes[i]
- local new = nil
if type(codes) == "table" then
local method = codes[1]
if method == "discretionary" then
local pre, post, replace = codes[2], codes[3], codes[4]
- new = new_disc()
if pre then
- setfield(new,"pre",tonodes(pre,last))
+ pre = tonodes(pre,last)
end
if post then
- setfield(new,"post",tonodes(post,last))
+ post = tonodes(post,last)
end
if replace then
- setfield(new,"replace",tonodes(replace,last))
+ replace = tonodes(replace,last)
end
+ -- todo: also set attr
+ local new = new_disc(pre,post,replace)
+ setattrlist(new,last)
head, current = insert_after(head,current,new)
elseif method == "noligature" then
-- not that efficient to copy but ok for testing
local list = codes[2]
if list then
for i=1,#list do
- new = copy_node(last)
+ local new = copy_node(last)
setchar(new,list[i])
setattr(new,a_noligature,1)
head, current = insert_after(head,current,new)
end
else
- new = copy_node(last)
+ local new = copy_node(last)
setchar(new,zwnj)
head, current = insert_after(head,current,new)
end
@@ -257,7 +262,7 @@ function replacements.handler(head)
-- todo
end
else
- new = copy_node(last)
+ local new = copy_node(last)
setchar(new,codes)
head, current = insert_after(head,current,new)
end
@@ -310,7 +315,7 @@ function replacements.set(n)
else
n = lists[n].attribute
if not enabled then
- nodes.tasks.enableaction("processors","languages.replacements.handler")
+ enableaction("processors","languages.replacements.handler")
if trace_replacements then
report_replacement("enabling replacement handler")
end
diff --git a/tex/context/base/mkiv/lang-wrd.lua b/tex/context/base/mkiv/lang-wrd.lua
index 38e6187af..8b6e48401 100644
--- a/tex/context/base/mkiv/lang-wrd.lua
+++ b/tex/context/base/mkiv/lang-wrd.lua
@@ -38,6 +38,7 @@ local getid = nuts.getid
local getsubtype = nuts.getsubtype
local getchar = nuts.getchar
local setattr = nuts.setattr
+local getlang = nuts.getlang
local isglyph = nuts.isglyph
local traverse_nodes = nuts.traverse
@@ -45,7 +46,7 @@ local traverse_ids = nuts.traverse_id
local wordsdata = words.data
local chardata = characters.data
-local tasks = nodes.tasks
+local enableaction = nodes.tasks.enableaction
local unsetvalue = attributes.unsetvalue
@@ -161,7 +162,7 @@ local function mark_words(head,whenfound) -- can be optimized and shared
while current do
local code, id = isglyph(current)
if code then
- local a = getfield(current,"lang")
+ local a = getlang(current)
if a then
if a ~= language then
if s > 0 then
@@ -234,7 +235,7 @@ function words.enable(settings)
if e then
e(settings)
end
- tasks.enableaction("processors","languages.words.check")
+ enableaction("processors","languages.words.check")
enabled = true
end
diff --git a/tex/context/base/mkiv/lpdf-ano.lua b/tex/context/base/mkiv/lpdf-ano.lua
index 138388c7c..e89bda12b 100644
--- a/tex/context/base/mkiv/lpdf-ano.lua
+++ b/tex/context/base/mkiv/lpdf-ano.lua
@@ -229,7 +229,6 @@ luatex.registerstopactions(function()
end
end)
-
local function pdfnametree(destinations)
local slices = { }
local sorted = table.sortedkeys(destinations)
diff --git a/tex/context/base/mkiv/lpdf-mis.lua b/tex/context/base/mkiv/lpdf-mis.lua
index 8d2e85ad2..dc3f8560a 100644
--- a/tex/context/base/mkiv/lpdf-mis.lua
+++ b/tex/context/base/mkiv/lpdf-mis.lua
@@ -442,10 +442,10 @@ local function documentspecification()
addtocatalog("Version", pdfconstant(format("1.%s",pdf.getminorversion())))
end
--- temp hack: the mediabox is not under our control and has a precision of 4 digits
+-- temp hack: the mediabox is not under our control and has a precision of 5 digits
local factor = number.dimenfactors.bp
-local f_value = formatters["%0.4F"]
+local f_value = formatters["%0.5F"]
local function boxvalue(n) -- we could share them
return pdfverbose(f_value(factor * n))
diff --git a/tex/context/base/mkiv/lpdf-res.lua b/tex/context/base/mkiv/lpdf-res.lua
index ca092c772..ac9478488 100644
--- a/tex/context/base/mkiv/lpdf-res.lua
+++ b/tex/context/base/mkiv/lpdf-res.lua
@@ -12,7 +12,7 @@ local implement = interfaces.implement
local nuts = nodes.nuts
local tonut = nodes.tonut
-local setfield = nuts.setfield
+local setwhd = nuts.setwhd
local setlist = nuts.setlist
local new_hlist = nuts.pool.hlist
@@ -29,9 +29,7 @@ function codeinjections.restoreboxresource(index)
local hbox = new_hlist()
local list, wd, ht, dp = useboxresource(index)
setlist(hbox,tonut(list))
- setfield(hbox,"width", wd)
- setfield(hbox,"height", ht)
- setfield(hbox,"depth", dp)
+ setwhd(hbox,wd,ht,dp)
return hbox -- so we return a nut !
end
diff --git a/tex/context/base/mkiv/lpdf-tag.lua b/tex/context/base/mkiv/lpdf-tag.lua
index 3167aeb5c..e33c8a811 100644
--- a/tex/context/base/mkiv/lpdf-tag.lua
+++ b/tex/context/base/mkiv/lpdf-tag.lua
@@ -24,7 +24,7 @@ local nodes = nodes
local nodeinjections = backends.pdf.nodeinjections
local codeinjections = backends.pdf.codeinjections
-local tasks = nodes.tasks
+local enableaction = nodes.tasks.enableaction
local pdfdictionary = lpdf.dictionary
local pdfarray = lpdf.array
@@ -602,9 +602,9 @@ end
function codeinjections.enabletags(tg,lb)
structures.tags.handler = nodeinjections.addtags
- tasks.enableaction("shipouts","structures.tags.handler")
- tasks.enableaction("shipouts","nodes.handlers.accessibility")
- tasks.enableaction("math","noads.handlers.tags")
+ enableaction("shipouts","structures.tags.handler")
+ enableaction("shipouts","nodes.handlers.accessibility")
+ enableaction("math","noads.handlers.tags")
-- maybe also textblock
if trace_tags then
report_tags("enabling structure tags")
diff --git a/tex/context/base/mkiv/luat-cbk.lua b/tex/context/base/mkiv/luat-cbk.lua
index 2c3bede72..7b28b3be4 100644
--- a/tex/context/base/mkiv/luat-cbk.lua
+++ b/tex/context/base/mkiv/luat-cbk.lua
@@ -70,9 +70,12 @@ directives.register("system.callbacks.permitoverloads", function(v)
end
end)
-sandbox.initializer(function()
- block_overloads = true
-end)
+sandbox.initializer {
+ category = "functions",
+ action = function()
+ block_overloads = true
+ end
+}
if not list then -- otherwise counters get reset
diff --git a/tex/context/base/mkiv/luat-cod.lua b/tex/context/base/mkiv/luat-cod.lua
index f62396a8e..31860db78 100644
--- a/tex/context/base/mkiv/luat-cod.lua
+++ b/tex/context/base/mkiv/luat-cod.lua
@@ -6,7 +6,7 @@ if not modules then modules = { } end modules ['luat-cod'] = {
license = "see context related readme files"
}
-local type, loadfile = type, loadfile
+local type, loadfile, tonumber = type, loadfile, tonumber
local match, gsub, find, format = string.match, string.gsub, string.find, string.format
local texconfig, lua = texconfig, lua
@@ -96,7 +96,29 @@ local targetpath = "."
-- environment.jobname = tex.jobname
-- environment.version = tostring(tex.toks.contextversiontoks)
-environment.initex = tex.formatname == ""
+if LUATEXVERION == nil then
+ LUATEXVERSION = status.luatex_version/100
+ + tonumber(status.luatex_revision)/1000
+end
+
+if LUATEXENGINE == nil then
+ LUATEXENGINE = status.luatex_engine and string.lower(status.luatex_engine)
+ or (find(status.banner,"LuajitTeX") and "luajittex" or "luatex")
+end
+
+if JITSUPPORTED == nil then
+ JITSUPPORTED = LUATEXENGINE == "luajittex" or jit
+end
+
+if INITEXMODE == nil then
+ INITEXMODE = status.ini_version
+end
+
+environment.initex = INITEXMODE
+environment.initexmode = INITEXMODE
+environment.luatexversion = LUATEXVERSION
+environment.luatexengine = LUATEXENGINE
+environment.jitsupported = JITSUPPORTED
if not environment.luafilechunk then
diff --git a/tex/context/base/mkiv/luat-exe.lua b/tex/context/base/mkiv/luat-exe.lua
index d8d954a30..1e9811218 100644
--- a/tex/context/base/mkiv/luat-exe.lua
+++ b/tex/context/base/mkiv/luat-exe.lua
@@ -8,66 +8,118 @@ if not modules then modules = { } end modules ['luat-exe'] = {
if not sandbox then require("l-sandbox") require("util-sbx") end -- for testing
+-- Ok, as usual, after finishing some code, I rewarded myself with searching youtube for
+-- new music ... this time I ran into the swedisch group 'wintergatan' (search for: marble
+-- machine) ... mechanical computers are so much more fun than the ones needed for running
+-- the code below. Nice videos (and shows) too ...
+
local type = type
-local executers = resolvers.executers or { }
-resolvers.executers = executers
+local executers = resolvers.executers or { }
+resolvers.executers = executers
-local disablerunners = sandbox.disablerunners
-local registerbinary = sandbox.registerbinary
-local registerroot = sandbox.registerroot
+local disablerunners = sandbox.disablerunners
+local disablelibraries = sandbox.disablelibraries
+local registerbinary = sandbox.registerbinary
+local registerlibrary = sandbox.registerlibrary
+local registerroot = sandbox.registerroot
-local lpegmatch = lpeg.match
+local lpegmatch = lpeg.match
-local sc_splitter = lpeg.tsplitat(";")
-local cm_splitter = lpeg.tsplitat(",")
+local sc_splitter = lpeg.tsplitat(";")
+local cm_splitter = lpeg.tsplitat(",")
local execution_mode directives.register("system.executionmode", function(v) execution_mode = v end)
local execution_list directives.register("system.executionlist", function(v) execution_list = v end)
local root_list directives.register("system.rootlist", function(v) root_list = v end)
+local library_mode directives.register("system.librarymode", function(v) library_mode = v end)
+local library_list directives.register("system.librarylist", function(v) library_list = v end)
-sandbox.initializer(function()
- if execution_mode == "none" then
- -- will be done later
- elseif execution_mode == "list" then
- if type(execution_list) == "string" then
- execution_list = lpegmatch(cm_splitter,execution_list)
- end
- if type(execution_list) == "table" then
- for i=1,#execution_list do
- registerbinary(execution_list[i])
+sandbox.initializer {
+ category = "binaries",
+ action = function()
+ if execution_mode == "none" then
+ -- will be done later
+ elseif execution_mode == "list" then
+ if type(execution_list) == "string" then
+ execution_list = lpegmatch(cm_splitter,execution_list)
+ end
+ if type(execution_list) == "table" then
+ for i=1,#execution_list do
+ registerbinary(execution_list[i])
+ end
end
+ else
+ registerbinary(true) -- all
end
- else
- -- whatever else we have configured
end
-end)
+}
-sandbox.initializer(function()
- if type(root_list) == "string" then
- root_list = lpegmatch(sc_splitter,root_list)
+sandbox.finalizer {
+ category = "binaries",
+ action = function()
+ if execution_mode == "none" then
+ disablerunners()
+ end
end
- if type(root_list) == "table" then
- for i=1,#root_list do
- local entry = root_list[i]
- if entry ~= "" then
- registerroot(entry)
+}
+
+sandbox.initializer {
+ category = "libraries",
+ action = function()
+ if library_mode == "none" then
+ -- will be done later
+ elseif library_mode == "list" then
+ if type(library_list) == "string" then
+ library_list = lpegmatch(cm_splitter,library_list)
+ end
+ if type(library_list) == "table" then
+ for i=1,#library_list do
+ registerlibrary(library_list[i])
+ end
end
+ else
+ registerlibrary(true) -- all
+ end
+ end
+}
+
+sandbox.finalizer {
+ category = "libraries",
+ action = function()
+ if library_mode == "none" then
+ disablelibraries()
end
end
-end)
+}
-sandbox.finalizer(function()
- if execution_mode == "none" then
- disablerunners()
+-- A bit of file system protection.
+
+sandbox.initializer{
+ category = "files",
+ action = function ()
+ if type(root_list) == "string" then
+ root_list = lpegmatch(sc_splitter,root_list)
+ end
+ if type(root_list) == "table" then
+ for i=1,#root_list do
+ local entry = root_list[i]
+ if entry ~= "" then
+ registerroot(entry)
+ end
+ end
+ end
end
-end)
+}
-- Let's prevent abuse of these libraries (built-in support still works).
-sandbox.finalizer(function()
- mplib = nil
- epdf = nil
- zip = nil
- fontloader = nil
-end)
+sandbox.finalizer {
+ category = "functions",
+ action = function()
+ mplib = nil
+ epdf = nil
+ zip = nil
+ fontloader = nil
+ end
+}
diff --git a/tex/context/base/mkiv/luat-fmt.lua b/tex/context/base/mkiv/luat-fmt.lua
index b5ea5685a..fe3c1042c 100644
--- a/tex/context/base/mkiv/luat-fmt.lua
+++ b/tex/context/base/mkiv/luat-fmt.lua
@@ -51,6 +51,33 @@ end
-- The silent option is Taco. It's a bit of a hack because we cannot yet mess
-- with directives. In fact, I could probably clean up the maker a bit by now.
+local template = [[--ini %primaryflags% --lua="%luafile%" "%texfile%" %secondaryflags% %dump% %redirect%]]
+local checkers = {
+ primaryflags = "string",
+ secondaryflags = "string",
+ luafile = "readable", -- "cache"
+ texfile = "readable", -- "cache"
+ redirect = "string",
+ dump = "string",
+}
+
+local runners = {
+ luatex = sandbox.registerrunner {
+ name = "make luatex format",
+ program = "luatex",
+ template = template,
+ checkers = checkers,
+ reporter = report_format,
+ },
+ luajittex = sandbox.registerrunner {
+ name = "make luajittex format",
+ program = "luajittex",
+ template = template,
+ checkers = checkers,
+ reporter = report_format,
+ },
+}
+
function environment.make_format(name,arguments)
local engine = environment.ownmain or "luatex"
local silent = environment.arguments.silent
@@ -116,13 +143,20 @@ function environment.make_format(name,arguments)
return
end
-- generate format
- local dump = os.platform=="unix" and "\\\\dump" or "\\dump"
- local command = format("%s --ini %s --lua=%s %s %s %s",
- engine,primaryflags(),quoted(usedluastub),quoted(fulltexsourcename),secondaryflags(),dump)
- if silent then
+ local specification = {
+ primaryflags = primaryflags(),
+ secondaryflags = secondaryflags(),
+ luafile = usedluastub,
+ texfile = fulltexsourcename,
+ dump = os.platform == "unix" and "\\\\dump" or "\\dump",
+ }
+ local runner = runners[engine]
+ if not runner then
+ report_format("format %a cannot be generated, no runner available for engine %a",name,engine)
+ elseif silent then
statistics.starttiming()
- local command = format("%s > temp.log",command)
- local result = os.execute(command)
+ specification.redirect = "> temp.log"
+ local result = makeformat(specification)
local runtime = statistics.stoptiming()
if result ~= 0 then
print(format("%s silent make > fatal error when making format %q",engine,name)) -- we use a basic print
@@ -131,8 +165,7 @@ function environment.make_format(name,arguments)
end
os.remove("temp.log")
else
- report_format("running command: %s\n",command)
- os.execute(command)
+ makeformat(specification)
end
-- remove related mem files
local pattern = file.removesuffix(file.basename(usedluastub)).."-*.mem"
diff --git a/tex/context/base/mkiv/luat-ini.lua b/tex/context/base/mkiv/luat-ini.lua
index cd1f45692..3ea8551c8 100644
--- a/tex/context/base/mkiv/luat-ini.lua
+++ b/tex/context/base/mkiv/luat-ini.lua
@@ -25,4 +25,12 @@ if not global then
global = _G
end
-LUATEXVERSION = status.luatex_version/100 + tonumber(status.luatex_revision)/1000
+LUATEXVERSION = status.luatex_version/100
+ + tonumber(status.luatex_revision)/1000
+
+LUATEXENGINE = status.luatex_engine and string.lower(status.luatex_engine)
+ or (string.find(status.banner,"LuajitTeX") and "luajittex" or "luatex")
+
+JITSUPPORTED = LUATEXENGINE == "luajittex" or jit
+
+INITEXMODE = status.ini_version
diff --git a/tex/context/base/mkiv/luat-iop.lua b/tex/context/base/mkiv/luat-iop.lua
index e1772af4e..34cc74e3e 100644
--- a/tex/context/base/mkiv/luat-iop.lua
+++ b/tex/context/base/mkiv/luat-iop.lua
@@ -9,16 +9,19 @@ if not modules then modules = { } end modules ['luat-iop'] = {
local cleanedpathlist = resolvers.cleanedpathlist
local registerroot = sandbox.registerroot
-sandbox.initializer(function()
- local function register(str,mode)
- local trees = cleanedpathlist(str)
- for i=1,#trees do
- registerroot(trees[i],mode)
+sandbox.initializer {
+ category = "files",
+ action = function()
+ local function register(str,mode)
+ local trees = cleanedpathlist(str)
+ for i=1,#trees do
+ registerroot(trees[i],mode)
+ end
end
+ register("TEXMF","read")
+ register("TEXINPUTS","read")
+ register("MPINPUTS","read")
+ -- register("TEXMFCACHE","write")
+ registerroot(".","write")
end
- register("TEXMF","read")
- register("TEXINPUTS","read")
- register("MPINPUTS","read")
- -- register("TEXMFCACHE","write")
- registerroot(".","write")
-end)
+}
diff --git a/tex/context/base/mkiv/lxml-ini.lua b/tex/context/base/mkiv/lxml-ini.lua
index 6026b1090..11f634739 100644
--- a/tex/context/base/mkiv/lxml-ini.lua
+++ b/tex/context/base/mkiv/lxml-ini.lua
@@ -41,6 +41,8 @@ implement { name = "xmldoifelseselfempty", actions = lxml.doifelseempty, arg
--------- { name = "xmlflushstripped", actions = lxml.strip, arguments = { "string", true } }
implement { name = "xmlall", actions = lxml.all, arguments = { "string", "string" } }
implement { name = "xmllastmatch", actions = lxml.lastmatch }
+implement { name = "xmlpushmatch", actions = lxml.pushmatch }
+implement { name = "xmlpopmatch", actions = lxml.popmatch }
implement { name = "xmlatt", actions = lxml.att, arguments = { "string", "string" } }
implement { name = "xmllastatt", actions = lxml.lastatt }
implement { name = "xmlattdef", actions = lxml.att, arguments = { "string", "string", "string" } }
diff --git a/tex/context/base/mkiv/lxml-ini.mkiv b/tex/context/base/mkiv/lxml-ini.mkiv
index bf641f10b..6ba6bc8d4 100644
--- a/tex/context/base/mkiv/lxml-ini.mkiv
+++ b/tex/context/base/mkiv/lxml-ini.mkiv
@@ -82,6 +82,8 @@
\let\xmllast \clf_xmllast
\let\xmllastatt \clf_xmllastatt
\let\xmllastmatch \clf_xmllastmatch
+\let\xmlpushmatch \clf_xmlpushmatch
+\let\xmlpopmatch \clf_xmlpopmatch
\let\xmlloaddirectives \clf_xmlloaddirectives
\let\xmlmain \clf_xmlmain
\let\xmlmatch \clf_xmlmatch
diff --git a/tex/context/base/mkiv/lxml-lpt.lua b/tex/context/base/mkiv/lxml-lpt.lua
index 19d69076a..939a737ab 100644
--- a/tex/context/base/mkiv/lxml-lpt.lua
+++ b/tex/context/base/mkiv/lxml-lpt.lua
@@ -820,36 +820,38 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving some p
+ V("s_parent")
+ V("s_self")
+ V("s_root")
- + V("s_ancestor"),
+ + V("s_ancestor")
+ + V("s_lastmatch"),
shortcuts = V("shortcuts_a") * (spaces * "/" * spaces * V("shortcuts_a"))^0,
s_descendant_or_self = (P("***/") + P("/")) * Cc(register_descendant_or_self), --- *** is a bonus
s_descendant = P("**") * Cc(register_descendant),
- s_child = P("*") * no_nextcolon * Cc(register_child ),
- s_parent = P("..") * Cc(register_parent ),
- s_self = P("." ) * Cc(register_self ),
- s_root = P("^^") * Cc(register_root ),
- s_ancestor = P("^") * Cc(register_ancestor ),
+ s_child = P("*") * no_nextcolon * Cc(register_child),
+ s_parent = P("..") * Cc(register_parent),
+ s_self = P("." ) * Cc(register_self),
+ s_root = P("^^") * Cc(register_root),
+ s_ancestor = P("^") * Cc(register_ancestor),
+ s_lastmatch = P("=") * Cc(register_last_match),
-- we can speed this up when needed but we cache anyway so ...
- descendant = P("descendant::") * Cc(register_descendant ),
- child = P("child::") * Cc(register_child ),
- parent = P("parent::") * Cc(register_parent ),
- self = P("self::") * Cc(register_self ),
- root = P('root::') * Cc(register_root ),
- ancestor = P('ancestor::') * Cc(register_ancestor ),
- descendant_or_self = P('descendant-or-self::') * Cc(register_descendant_or_self ),
- ancestor_or_self = P('ancestor-or-self::') * Cc(register_ancestor_or_self ),
- -- attribute = P('attribute::') * Cc(register_attribute ),
- -- namespace = P('namespace::') * Cc(register_namespace ),
- following = P('following::') * Cc(register_following ),
- following_sibling = P('following-sibling::') * Cc(register_following_sibling ),
- preceding = P('preceding::') * Cc(register_preceding ),
- preceding_sibling = P('preceding-sibling::') * Cc(register_preceding_sibling ),
- reverse_sibling = P('reverse-sibling::') * Cc(register_reverse_sibling ),
- last_match = P('last-match::') * Cc(register_last_match ),
+ descendant = P("descendant::") * Cc(register_descendant),
+ child = P("child::") * Cc(register_child),
+ parent = P("parent::") * Cc(register_parent),
+ self = P("self::") * Cc(register_self),
+ root = P('root::') * Cc(register_root),
+ ancestor = P('ancestor::') * Cc(register_ancestor),
+ descendant_or_self = P('descendant-or-self::') * Cc(register_descendant_or_self),
+ ancestor_or_self = P('ancestor-or-self::') * Cc(register_ancestor_or_self),
+ -- attribute = P('attribute::') * Cc(register_attribute),
+ -- namespace = P('namespace::') * Cc(register_namespace),
+ following = P('following::') * Cc(register_following),
+ following_sibling = P('following-sibling::') * Cc(register_following_sibling),
+ preceding = P('preceding::') * Cc(register_preceding),
+ preceding_sibling = P('preceding-sibling::') * Cc(register_preceding_sibling),
+ reverse_sibling = P('reverse-sibling::') * Cc(register_reverse_sibling),
+ last_match = P('last-match::') * Cc(register_last_match),
selector = P("{") * C((1-P("}"))^1) * P("}") / register_selector,
@@ -1197,6 +1199,16 @@ do
return lastmatch
end
+ local stack = { }
+
+ function xml.pushmatch()
+ insert(stack,lastmatch)
+ end
+
+ function xml.popmatch()
+ lastmatch = remove(stack)
+ end
+
end
local applylpath = xml.applylpath
diff --git a/tex/context/base/mkiv/lxml-tex.lua b/tex/context/base/mkiv/lxml-tex.lua
index fc86b9460..582185ba8 100644
--- a/tex/context/base/mkiv/lxml-tex.lua
+++ b/tex/context/base/mkiv/lxml-tex.lua
@@ -53,7 +53,8 @@ local xmlinclusions = xml.inclusions
local xmlbadinclusions = xml.badinclusions
local xmlcontent = xml.content
local xmllastmatch = xml.lastmatch
-
+local xmlpushmatch = xml.pushmatch
+local xmlpopmatch = xml.popmatch
directives.enable("xml.path.keeplastmatch")
@@ -1943,6 +1944,9 @@ function lxml.lastmatch()
end
end
+lxml.pushmatch = xmlpushmatch
+lxml.popmatch = xmlpopmatch
+
function lxml.snippet(id,i)
local e = getid(id)
if e then
diff --git a/tex/context/base/mkiv/math-dir.lua b/tex/context/base/mkiv/math-dir.lua
index 6978ba3b5..cba991b84 100644
--- a/tex/context/base/mkiv/math-dir.lua
+++ b/tex/context/base/mkiv/math-dir.lua
@@ -41,7 +41,7 @@ local insert_node_before = nuts.insert_before
local insert_node_after = nuts.insert_after
local nodecodes = nodes.nodecodes
-local tasks = nodes.tasks
+local enableaction = nodes.tasks.enableaction
local glyph_code = nodecodes.glyph
local hlist_code = nodecodes.hlist
@@ -160,7 +160,7 @@ function directions.setmath(n)
if trace_directions then
report_directions("enabling directions handler")
end
- tasks.enableaction("math","typesetters.directions.processmath")
+ enableaction("math","typesetters.directions.processmath")
enabled = true
end
end
diff --git a/tex/context/base/mkiv/math-ini.lua b/tex/context/base/mkiv/math-ini.lua
index de7592c87..321014d94 100644
--- a/tex/context/base/mkiv/math-ini.lua
+++ b/tex/context/base/mkiv/math-ini.lua
@@ -189,32 +189,16 @@ local escapes = characters.filters.utf.private.escapes
-- not that many so no need to reuse tables
-local setmathcharacter
-
-if LUATEXVERSION > 0.98 then
- setmathcharacter = function(class,family,slot,unicode,mset,dset)
- if mset and codes[class] then -- regular codes < 7
- setmathcode("global",slot,class,family,unicode)
- mset = false
- end
- if dset and class == open_class or class == close_class or class == middle_class then
- setdelcode("global",slot,family,unicode,0,0)
- dset = false
- end
- return mset, dset
+local setmathcharacter = function(class,family,slot,unicode,mset,dset)
+ if mset and codes[class] then -- regular codes < 7
+ setmathcode("global",slot,class,family,unicode)
+ mset = false
end
-else
- setmathcharacter = function(class,family,slot,unicode,mset,dset)
- if mset and codes[class] then -- regular codes < 7
- setmathcode("global",slot,{class,family,unicode})
- mset = false
- end
- if dset and class == open_class or class == close_class or class == middle_class then
- setdelcode("global",slot,{family,unicode,0,0})
- dset = false
- end
- return mset, dset
+ if dset and class == open_class or class == close_class or class == middle_class then
+ setdelcode("global",slot,family,unicode,0,0)
+ dset = false
end
+ return mset, dset
end
local f_accent = formatters[ [[\ugdef\%s{\Umathaccent 0 "%X "%X }]] ]
diff --git a/tex/context/base/mkiv/math-ini.mkiv b/tex/context/base/mkiv/math-ini.mkiv
index 90478771e..3b57c56da 100644
--- a/tex/context/base/mkiv/math-ini.mkiv
+++ b/tex/context/base/mkiv/math-ini.mkiv
@@ -118,6 +118,7 @@
\definesystemattribute[mathcategory] [public]
\definesystemattribute[mathmode] [public]
\definesystemattribute[mathitalics] [public]
+\definesystemattribute[mathkernpairs] [public]
\definesystemattribute[mathbidi] [public]
\definesystemattribute[mathdomain] [public]
@@ -237,7 +238,9 @@
\def\math_m_yes_text[#1]%
{\begingroup
- \edef\currentmathematics{#1}% check for valid
+ \doifassignmentelse{#1}%
+ {\setupcurrentmathematics[#1]}%
+ {\edef\currentmathematics{#1}}% check for valid
\edef\p_openup{\mathematicsparameter\c!openup}%
\ifx\p_openup\v!yes
\expandafter\math_m_yes_text_openedup
@@ -1357,6 +1360,31 @@
% \csname\??mathitalics\mathematicsparameter\s!italics\endcsname
% \to \everyswitchmathematics % only in mathematics
+%D Math kerns (experiment)
+
+\installcorenamespace{mathkernpairs}
+
+\setnewconstant\c_math_kernpairs_attribute\attributeunsetvalue % no real need for an extra constant
+
+\def\math_kernpairs_initialize
+ {\ifnum\c_math_kernpairs_attribute=\attributeunsetvalue \else
+ \clf_initializemathkernpairs % one time
+ \global\let\math_kernpairs_initialize\relax
+ \fi}
+
+\appendtoks
+ \edef\p_kernpairs{\mathematicsparameter\s!kernpairs}%
+ \c_math_kernpairs_attribute\ifx\p_kernpairs\v!yes\plusone\else\attributeunsetvalue\fi\relax
+\to \everyswitchmathematics % only in mathematics
+
+\appendtoks
+ \math_kernpairs_initialize
+ \attribute\mathkernpairsattribute\c_math_kernpairs_attribute
+\to \everymathematics
+
+\setupmathematics
+ [\s!kernpairs=\v!no]
+
%D \macros
%D {enablemathpunctuation,disablemathpunctuation}
%D
diff --git a/tex/context/base/mkiv/math-noa.lua b/tex/context/base/mkiv/math-noa.lua
index 2b0d7b73f..fb08c4ef4 100644
--- a/tex/context/base/mkiv/math-noa.lua
+++ b/tex/context/base/mkiv/math-noa.lua
@@ -56,6 +56,7 @@ local trace_goodies = false registertracker("math.goodies", function
local trace_variants = false registertracker("math.variants", function(v) trace_variants = v end)
local trace_alternates = false registertracker("math.alternates", function(v) trace_alternates = v end)
local trace_italics = false registertracker("math.italics", function(v) trace_italics = v end)
+local trace_kernpairs = false registertracker("math.kernpairs", function(v) trace_kernpairs = v end)
local trace_domains = false registertracker("math.domains", function(v) trace_domains = v end)
local trace_families = false registertracker("math.families", function(v) trace_families = v end)
local trace_fences = false registertracker("math.fences", function(v) trace_fences = v end)
@@ -71,6 +72,7 @@ local report_goodies = logreporter("mathematics","goodies")
local report_variants = logreporter("mathematics","variants")
local report_alternates = logreporter("mathematics","alternates")
local report_italics = logreporter("mathematics","italics")
+local report_kernpairs = logreporter("mathematics","kernpairs")
local report_domains = logreporter("mathematics","domains")
local report_families = logreporter("mathematics","families")
local report_fences = logreporter("mathematics","fences")
@@ -86,6 +88,7 @@ local nutstring = nuts.tostring
local setfield = nuts.setfield
local setlink = nuts.setlink
+local setlist = nuts.setlist
local setnext = nuts.setnext
local setprev = nuts.setprev
local setchar = nuts.setchar
@@ -101,6 +104,15 @@ local getsubtype = nuts.getsubtype
local getchar = nuts.getchar
local getfont = nuts.getfont
local getattr = nuts.getattr
+local getlist = nuts.getlist
+
+local getnucleus = nuts.getnucleus
+local getsub = nuts.getsub
+local getsup = nuts.getsup
+
+local setnucleus = nuts.setnucleus
+local setsub = nuts.setsub
+local setsup = nuts.setsup
local flush_node = nuts.flush
local new_node = nuts.new -- todo: pool: math_noad math_sub
@@ -139,6 +151,8 @@ noads.handlers = noads.handlers or { }
local handlers = noads.handlers
local tasks = nodes.tasks
+local enableaction = tasks.enableaction
+local setaction = tasks.setaction
local nodecodes = nodes.nodecodes
local noadcodes = nodes.noadcodes
@@ -175,6 +189,9 @@ local right_fence_code = fencecodes.right
-- this initial stuff is tricky as we can have removed and new nodes with the same address
-- the only way out is a free-per-page list of nodes (not bad anyway)
+-- local gf = getfield local gt = setmetatableindex("number") getfield = function(n,f) gt[f] = gt[f] + 1 return gf(n,f) end mathematics.GETFIELD = gt
+-- local sf = setfield local st = setmetatableindex("number") setfield = function(n,f,v) st[f] = st[f] + 1 sf(n,f,v) end mathematics.SETFIELD = st
+
local function process(start,what,n,parent)
if n then
n = n + 1
@@ -223,13 +240,13 @@ local function process(start,what,n,parent)
end
elseif id == math_noad then
-- single characters are like this
- local noad = getfield(start,"nucleus") if noad then process(noad,what,n,start) end -- list
- noad = getfield(start,"sup") if noad then process(noad,what,n,start) end -- list
- noad = getfield(start,"sub") if noad then process(noad,what,n,start) end -- list
+ local noad = getnucleus(start) if noad then process(noad,what,n,start) end -- list
+ noad = getsup (start) if noad then process(noad,what,n,start) end -- list
+ noad = getsub (start) if noad then process(noad,what,n,start) end -- list
elseif id == math_char or id == math_textchar or id == math_delim then
break
elseif id == math_box or id == math_sub then
- local noad = getfield(start,"list") if noad then process(noad,what,n,start) end -- list (not getlist !)
+ local noad = getlist(start) if noad then process(noad,what,n,start) end -- list (not getlist !)
elseif id == math_fraction then
local noad = getfield(start,"num") if noad then process(noad,what,n,start) end -- list
noad = getfield(start,"denom") if noad then process(noad,what,n,start) end -- list
@@ -243,15 +260,15 @@ local function process(start,what,n,parent)
elseif id == math_fence then
local noad = getfield(start,"delim") if noad then process(noad,what,n,start) end -- delimiter
elseif id == math_radical then
- local noad = getfield(start,"nucleus") if noad then process(noad,what,n,start) end -- list
- noad = getfield(start,"sup") if noad then process(noad,what,n,start) end -- list
- noad = getfield(start,"sub") if noad then process(noad,what,n,start) end -- list
+ local noad = getnucleus(start) if noad then process(noad,what,n,start) end -- list
+ noad = getsup (start) if noad then process(noad,what,n,start) end -- list
+ noad = getsub (start) if noad then process(noad,what,n,start) end -- list
noad = getfield(start,"left") if noad then process(noad,what,n,start) end -- delimiter
noad = getfield(start,"degree") if noad then process(noad,what,n,start) end -- list
elseif id == math_accent then
- local noad = getfield(start,"nucleus") if noad then process(noad,what,n,start) end -- list
- noad = getfield(start,"sup") if noad then process(noad,what,n,start) end -- list
- noad = getfield(start,"sub") if noad then process(noad,what,n,start) end -- list
+ local noad = getnucleus(start) if noad then process(noad,what,n,start) end -- list
+ noad = getsup (start) if noad then process(noad,what,n,start) end -- list
+ noad = getsub (start) if noad then process(noad,what,n,start) end -- list
noad = getfield(start,"accent") if noad then process(noad,what,n,start) end -- list
noad = getfield(start,"bot_accent") if noad then process(noad,what,n,start) end -- list
-- elseif id == math_style then
@@ -270,11 +287,11 @@ local function processnested(current,what,n)
local noad = nil
local id = getid(current)
if id == math_noad then
- noad = getfield(current,"nucleus") if noad then process(noad,what,n,current) end -- list
- noad = getfield(current,"sup") if noad then process(noad,what,n,current) end -- list
- noad = getfield(current,"sub") if noad then process(noad,what,n,current) end -- list
+ noad = getnucleus(current) if noad then process(noad,what,n,current) end -- list
+ noad = getsup (current) if noad then process(noad,what,n,current) end -- list
+ noad = getsub (current) if noad then process(noad,what,n,current) end -- list
elseif id == math_box or id == math_sub then
- noad = getfield(current,"list") if noad then process(noad,what,n,current) end -- list (not getlist !)
+ noad = getlist(current) if noad then process(noad,what,n,current) end -- list (not getlist !)
elseif id == math_fraction then
noad = getfield(current,"num") if noad then process(noad,what,n,current) end -- list
noad = getfield(current,"denom") if noad then process(noad,what,n,current) end -- list
@@ -288,15 +305,15 @@ local function processnested(current,what,n)
elseif id == math_fence then
noad = getfield(current,"delim") if noad then process(noad,what,n,current) end -- delimiter
elseif id == math_radical then
- noad = getfield(current,"nucleus") if noad then process(noad,what,n,current) end -- list
- noad = getfield(current,"sup") if noad then process(noad,what,n,current) end -- list
- noad = getfield(current,"sub") if noad then process(noad,what,n,current) end -- list
+ noad = getnucleus(current) if noad then process(noad,what,n,current) end -- list
+ noad = getsup (current) if noad then process(noad,what,n,current) end -- list
+ noad = getsub (current) if noad then process(noad,what,n,current) end -- list
noad = getfield(current,"left") if noad then process(noad,what,n,current) end -- delimiter
noad = getfield(current,"degree") if noad then process(noad,what,n,current) end -- list
elseif id == math_accent then
- noad = getfield(current,"nucleus") if noad then process(noad,what,n,current) end -- list
- noad = getfield(current,"sup") if noad then process(noad,what,n,current) end -- list
- noad = getfield(current,"sub") if noad then process(noad,what,n,current) end -- list
+ noad = getnucleus(current) if noad then process(noad,what,n,current) end -- list
+ noad = getsup (current) if noad then process(noad,what,n,current) end -- list
+ noad = getsub (current) if noad then process(noad,what,n,current) end -- list
noad = getfield(current,"accent") if noad then process(noad,what,n,current) end -- list
noad = getfield(current,"bot_accent") if noad then process(noad,what,n,current) end -- list
end
@@ -306,11 +323,11 @@ local function processstep(current,process,n,id)
local noad = nil
local id = id or getid(current)
if id == math_noad then
- noad = getfield(current,"nucleus") if noad then process(noad,n,current) end -- list
- noad = getfield(current,"sup") if noad then process(noad,n,current) end -- list
- noad = getfield(current,"sub") if noad then process(noad,n,current) end -- list
+ noad = getnucleus(current) if noad then process(noad,n,current) end -- list
+ noad = getsup (current) if noad then process(noad,n,current) end -- list
+ noad = getsub (current) if noad then process(noad,n,current) end -- list
elseif id == math_box or id == math_sub then
- noad = getfield(current,"list") if noad then process(noad,n,current) end -- list (not getlist !)
+ noad = getlist(current) if noad then process(noad,n,current) end -- list (not getlist !)
elseif id == math_fraction then
noad = getfield(current,"num") if noad then process(noad,n,current) end -- list
noad = getfield(current,"denom") if noad then process(noad,n,current) end -- list
@@ -324,15 +341,15 @@ local function processstep(current,process,n,id)
elseif id == math_fence then
noad = getfield(current,"delim") if noad then process(noad,n,current) end -- delimiter
elseif id == math_radical then
- noad = getfield(current,"nucleus") if noad then process(noad,n,current) end -- list
- noad = getfield(current,"sup") if noad then process(noad,n,current) end -- list
- noad = getfield(current,"sub") if noad then process(noad,n,current) end -- list
+ noad = getnucleus(current) if noad then process(noad,n,current) end -- list
+ noad = getsup (current) if noad then process(noad,n,current) end -- list
+ noad = getsub (current) if noad then process(noad,n,current) end -- list
noad = getfield(current,"left") if noad then process(noad,n,current) end -- delimiter
noad = getfield(current,"degree") if noad then process(noad,n,current) end -- list
elseif id == math_accent then
- noad = getfield(current,"nucleus") if noad then process(noad,n,current) end -- list
- noad = getfield(current,"sup") if noad then process(noad,n,current) end -- list
- noad = getfield(current,"sub") if noad then process(noad,n,current) end -- list
+ noad = getnucleus(current) if noad then process(noad,n,current) end -- list
+ noad = getsup (current) if noad then process(noad,n,current) end -- list
+ noad = getsub (current) if noad then process(noad,n,current) end -- list
noad = getfield(current,"accent") if noad then process(noad,n,current) end -- list
noad = getfield(current,"bot_accent") if noad then process(noad,n,current) end -- list
end
@@ -703,8 +720,8 @@ local function makefence(what,char)
local d = new_node(math_delim)
local f = new_node(math_fence)
if char then
- local sym = getfield(char,"nucleus")
- local chr = getfield(sym,"char")
+ local sym = getnucleus(char)
+ local chr = getchar(sym)
local fam = getfield(sym,"fam")
if chr == dummyfencechar then
chr = 0
@@ -720,9 +737,9 @@ end
local function makelist(noad,f_o,o_next,c_prev,f_c,middle)
local list = new_node(math_sub)
- setfield(list,"head",f_o)
+ setlist(list,f_o)
setsubtype(noad,noad_inner)
- setfield(noad,"nucleus",list)
+ setnucleus(noad,list)
setlink(f_o,o_next)
setlink(c_prev,f_c)
if middle and next(middle) then
@@ -733,12 +750,11 @@ local function makelist(noad,f_o,o_next,c_prev,f_c,middle)
if m then
local next = getnext(current)
local fence = makefence(middle_fence_code,current)
- setfield(current,"nucleus",nil)
+ setnucleus(current)
flush_node(current)
middle[current] = nil
-- replace_node
- setlink(prev,fence)
- setlink(fence,next)
+ setlink(prev,fence,next)
prev = fence
current = next
else
@@ -758,7 +774,7 @@ local function convert_both(open,close,middle)
local f_o = makefence(left_fence_code,open)
local f_c = makefence(right_fence_code,close)
makelist(open,f_o,o_next,c_prev,f_c,middle)
- setfield(close,"nucleus",nil)
+ setnucleus(close)
flush_node(close)
if c_next then
setprev(c_next,open)
@@ -877,7 +893,7 @@ implement {
name = "enableautofences",
onlyonce = true,
actions = function()
- tasks.enableaction("math","noads.handlers.autofences")
+ enableaction("math","noads.handlers.autofences")
enabled = true
end
}
@@ -904,8 +920,8 @@ local function replace(pointer,what,n,parent)
local start_super, stop_super, start_sub, stop_sub
local mode = "unset"
while next and getid(next) == math_noad do
- local nextnucleus = getfield(next,"nucleus")
- if nextnucleus and getid(nextnucleus) == math_char and not getfield(next,"sub") and not getfield(next,"sup") then
+ local nextnucleus = getnucleus(next)
+ if nextnucleus and getid(nextnucleus) == math_char and not getsub(next) and not getsup(next) then
local char = getchar(nextnucleus)
local s = superscripts[char]
if s then
@@ -948,11 +964,11 @@ local function replace(pointer,what,n,parent)
end
if start_super then
if start_super == stop_super then
- setfield(pointer,"sup",getfield(start_super,"nucleus"))
+ setsup(pointer,getnucleus(start_super))
else
local list = new_node(math_sub) -- todo attr
- setfield(list,"list",start_super)
- setfield(pointer,"sup",list)
+ setlist(list,start_super)
+ setsup(pointer,list)
end
if mode == "super" then
setnext(pointer,getnext(stop_super))
@@ -961,11 +977,11 @@ local function replace(pointer,what,n,parent)
end
if start_sub then
if start_sub == stop_sub then
- setfield(pointer,"sub",getfield(start_sub,"nucleus"))
+ setsub(pointer,getnucleus(start_sub))
else
local list = new_node(math_sub) -- todo attr
- setfield(list,"list",start_sub)
- setfield(pointer,"sub",list)
+ setlist(list,start_sub)
+ setsub(pointer,list)
end
if mode == "sub" then
setnext(pointer,getnext(stop_sub))
@@ -1237,9 +1253,9 @@ local c_negative_d = "trace:dr"
local function insert_kern(current,kern)
local sub = new_node(math_sub) -- todo: pool
local noad = new_node(math_noad) -- todo: pool
- setfield(sub,"list",kern)
+ setlist(sub,kern)
setnext(kern,noad)
- setfield(noad,"nucleus",current)
+ setnucleus(noad,current)
return sub
end
@@ -1341,7 +1357,7 @@ end
local enable
enable = function()
- tasks.enableaction("math", "noads.handlers.italics")
+ enableaction("math", "noads.handlers.italics")
if trace_italics then
report_italics("enabling math italics")
end
@@ -1393,6 +1409,80 @@ implement {
actions = mathematics.resetitalics
}
+do
+
+ -- math kerns (experiment) in goodies:
+ --
+ -- mathematics = {
+ -- kernpairs = {
+ -- [0x1D44E] = {
+ -- [0x1D44F] = 400, -- 𝑎𝑏
+ -- }
+ -- },
+ -- }
+
+ local a_kernpairs = privateattribute("mathkernpairs")
+ local kernpairs = { }
+
+ local function enable()
+ enableaction("math", "noads.handlers.kernpairs")
+ if trace_kernpairs then
+ report_kernpairs("enabling math kern pairs")
+ end
+ enable = false
+ end
+
+ implement {
+ name = "initializemathkernpairs",
+ actions = enable,
+ onlyonce = true,
+ }
+
+ local hash = setmetatableindex(function(t,font)
+ local g = fontdata[font].goodies
+ local m = g and g[1].mathematics
+ local k = m and m.kernpairs
+ t[font] = k
+ return k
+ end)
+
+ kernpairs[math_char] = function(pointer,what,n,parent)
+ if getattr(pointer,a_kernpairs) == 1 then
+ local font = getfont(pointer)
+ local list = hash[font]
+ if list then
+ local first = getchar(pointer)
+ local found = list[first]
+ if found then
+ local next = getnext(parent)
+ if next and getid(next) == math_noad then
+ pointer = getnucleus(next)
+ if pointer then
+ if getfont(pointer) == font then
+ local second = getchar(pointer)
+ local kern = found[second]
+ if kern then
+ kern = kern * fonts.hashes.parameters[font].hfactor
+ if trace_kernpairs then
+ report_kernpairs("adding %p kerning between %C and %C",kern,first,second)
+ end
+ setlink(parent,new_kern(kern),getnext(parent))
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+
+ function handlers.kernpairs(head,style,penalties)
+ processnoads(head,kernpairs,"kernpairs")
+ return true
+ end
+
+end
+
-- primes and such
local collapse = { } processors.collapse = collapse
@@ -1437,30 +1527,30 @@ local validpair = {
local function movesubscript(parent,current_nucleus,current_char)
local prev = getprev(parent)
if prev and getid(prev) == math_noad then
- if not getfield(prev,"sup") and not getfield(prev,"sub") then
+ if not getsup(prev) and not getsub(prev) then
-- {f} {'}_n => f_n^'
setchar(current_nucleus,movesub[current_char or getchar(current_nucleus)])
- local nucleus = getfield(parent,"nucleus")
- local sub = getfield(parent,"sub")
- local sup = getfield(parent,"sup")
- setfield(prev,"sup",nucleus)
- setfield(prev,"sub",sub)
+ local nucleus = getnucleus(parent)
+ local sub = getsub(parent)
+ local sup = getsup(parent)
+ setsup(prev,nucleus)
+ setsub(prev,sub)
local dummy = copy_node(nucleus)
setchar(dummy,0)
- setfield(parent,"nucleus",dummy)
- setfield(parent,"sub",nil)
+ setnucleus(parent,dummy)
+ setsub(parent)
if trace_collapsing then
report_collapsing("fixing subscript")
end
- elseif not getfield(prev,"sup") then
+ elseif not getsup(prev) then
-- {f} {'}_n => f_n^'
setchar(current_nucleus,movesub[current_char or getchar(current_nucleus)])
- local nucleus = getfield(parent,"nucleus")
- local sup = getfield(parent,"sup")
- setfield(prev,"sup",nucleus)
+ local nucleus = getnucleus(parent)
+ local sup = getsup(parent)
+ setsup(prev,nucleus)
local dummy = copy_node(nucleus)
setchar(dummy,0)
- setfield(parent,"nucleus",dummy)
+ setnucleus(parent,dummy)
if trace_collapsing then
report_collapsing("fixing subscript")
end
@@ -1471,16 +1561,16 @@ end
local function collapsepair(pointer,what,n,parent,nested) -- todo: switch to turn in on and off
if parent then
if validpair[getsubtype(parent)] then
- local current_nucleus = getfield(parent,"nucleus")
+ local current_nucleus = getnucleus(parent)
if getid(current_nucleus) == math_char then
local current_char = getchar(current_nucleus)
- if not getfield(parent,"sub") and not getfield(parent,"sup") then
+ if not getsub(parent) and not getsup(parent) then
local mathpair = mathpairs[current_char]
if mathpair then
local next_noad = getnext(parent)
if next_noad and getid(next_noad) == math_noad then
if validpair[getsubtype(next_noad)] then
- local next_nucleus = getfield(next_noad,"nucleus")
+ local next_nucleus = getnucleus(next_noad)
local next_char = getchar(next_nucleus)
if getid(next_nucleus) == math_char then
local newchar = mathpair[next_char]
@@ -1498,10 +1588,10 @@ local function collapsepair(pointer,what,n,parent,nested) -- todo: switch to tur
else
setnext(parent)
end
- setfield(parent,"sup",getfield(next_noad,"sup"))
- setfield(parent,"sub",getfield(next_noad,"sub"))
- setfield(next_noad,"sup",nil)
- setfield(next_noad,"sub",nil)
+ setsup(parent,getsup(next_noad))
+ setsub(parent,getsub(next_noad))
+ setsup(next_noad)
+ setsub(next_noad)
flush_node(next_noad)
collapsepair(pointer,what,n,parent,true)
-- if not nested and movesub[current_char] then
@@ -1560,7 +1650,7 @@ variants[math_char] = function(pointer,what,n,parent) -- also set export value
if selector then
local next = getnext(parent)
if next and getid(next) == math_noad then
- local nucleus = getfield(next,"nucleus")
+ local nucleus = getnucleus(next)
if nucleus and getid(nucleus) == math_char and getchar(nucleus) == selector then
local variant
local tfmdata = fontdata[getfont(pointer)]
@@ -1630,7 +1720,7 @@ function handlers.classes(head,style,penalties)
end
registertracker("math.classes",function(v)
- tasks.setaction("math","noads.handlers.classes",v)
+ setaction("math","noads.handlers.classes",v)
end)
-- experimental
@@ -1676,7 +1766,7 @@ do
local enable
enable = function()
- tasks.enableaction("math", "noads.handlers.domains")
+ enableaction("math", "noads.handlers.domains")
if trace_domains then
report_domains("enabling math domains")
end
@@ -1799,7 +1889,7 @@ function handlers.showtree(head,style,penalties)
end
registertracker("math.showtree",function(v)
- tasks.setaction("math","noads.handlers.showtree",v)
+ setaction("math","noads.handlers.showtree",v)
end)
-- also for me
@@ -1813,7 +1903,7 @@ end
registertracker("math.makeup",function(v)
visual = v
- tasks.setaction("math","noads.handlers.makeup",v)
+ setaction("math","noads.handlers.makeup",v)
end)
-- the normal builder
diff --git a/tex/context/base/mkiv/math-tag.lua b/tex/context/base/mkiv/math-tag.lua
index 975b894ec..13c8fffc7 100644
--- a/tex/context/base/mkiv/math-tag.lua
+++ b/tex/context/base/mkiv/math-tag.lua
@@ -30,6 +30,8 @@ local getdisc = nuts.getdisc
local getsubtype = nuts.getsubtype
local getattr = nuts.getattr
local setattr = nuts.setattr
+local getcomponents = nuts.getcomponents
+local getwidth = nuts.getwidth
local set_attributes = nuts.setattributes
local traverse_nodes = nuts.traverse
@@ -250,7 +252,7 @@ process = function(start) -- we cannot use the processor as we have no finalizer
if tag == "formulacaption" then
-- skip
elseif tag == "mstacker" then
- local list = getfield(start,"list")
+ local list = getlist(start)
if list then
process(list)
end
@@ -260,7 +262,7 @@ process = function(start) -- we cannot use the processor as we have no finalizer
end
local text = start_tagged(tag)
setattr(start,a_tagged,text)
- local list = getfield(start,"list")
+ local list = getlist(start)
if not list then
-- empty list
elseif not attr then
@@ -315,7 +317,7 @@ process = function(start) -- we cannot use the processor as we have no finalizer
if id == hlist_code or id == vlist_code then
runner(getlist(n),depth+1)
elseif id == glyph_code then
- runner(getfield(n,"components"),depth+1) -- this should not be needed
+ runner(getcomponents(n),depth+1) -- this should not be needed
elseif id == disc_code then
local pre, post, replace = getdisc(n)
runner(pre,depth+1) -- idem
@@ -335,7 +337,7 @@ process = function(start) -- we cannot use the processor as we have no finalizer
stop_tagged()
end
elseif id == math_sub_code then -- normally a hbox
- local list = getfield(start,"list")
+ local list = getlist(start)
if list then
local attr = getattr(start,a_tagged)
local last = attr and taglist[attr]
@@ -526,7 +528,7 @@ process = function(start) -- we cannot use the processor as we have no finalizer
processsubsup(start)
end
elseif id == glue_code then
- -- setattr(start,a_tagged,start_tagged("mspace",{ width = getfield(start,"width") }))
+ -- setattr(start,a_tagged,start_tagged("mspace",{ width = getwidth(start) }))
setattr(start,a_tagged,start_tagged("mspace"))
stop_tagged()
else
diff --git a/tex/context/base/mkiv/meta-imp-txt.mkiv b/tex/context/base/mkiv/meta-imp-txt.mkiv
index c6ecc6f03..b2a6d6d1d 100644
--- a/tex/context/base/mkiv/meta-imp-txt.mkiv
+++ b/tex/context/base/mkiv/meta-imp-txt.mkiv
@@ -289,6 +289,9 @@
fi ;
fi ;
endfor ;
+ if TraceRot :
+ draw boundingbox currentpicture withpen pencircle scaled .25pt withcolor blue ;
+ fi ;
enddef ;
\stopMPdefinitions
diff --git a/tex/context/base/mkiv/meta-tex.lua b/tex/context/base/mkiv/meta-tex.lua
index 205024fae..71207975d 100644
--- a/tex/context/base/mkiv/meta-tex.lua
+++ b/tex/context/base/mkiv/meta-tex.lua
@@ -241,7 +241,7 @@ local f_exptext = formatters[ [[textext("\mathematics{%s\times10^{%s}}")]] ]
local mpprint = mp.print
-function mp.format(fmt,str)
+function mp.format(fmt,str) -- bah, this overloads mp.format in mlib-lua.lua
fmt = lpegmatch(cleaner,fmt)
mpprint(f_textext(formatters[fmt](metapost.untagvariable(str,false))))
end
diff --git a/tex/context/base/mkiv/mlib-lua.lua b/tex/context/base/mkiv/mlib-lua.lua
index 8f24124b9..4198a7339 100644
--- a/tex/context/base/mkiv/mlib-lua.lua
+++ b/tex/context/base/mkiv/mlib-lua.lua
@@ -202,7 +202,7 @@ end
local replacer = lpeg.replacer("@","%%")
-function mp.format(fmt,...)
+function mp.fprint(fmt,...)
n = n + 1
if not find(fmt,"%%") then
fmt = lpegmatch(replacer,fmt)
@@ -539,3 +539,95 @@ mp._get_toks_ = mp.gettoks
mp._set_dimen_ = mp.setdimen
mp._set_count_ = mp.setcount
mp._set_toks_ = mp.settoks
+
+-- position fun
+
+do
+
+ local mprint = mp.print
+ local fprint = mp.fprint
+ local qprint = mp.quoted
+ local getwhd = job.positions.whd
+ local getxy = job.positions.xy
+ local getposition = job.positions.position
+ local getpage = job.positions.page
+ local getregion = job.positions.region
+ local getmacro = tokens.getters.macro
+
+ function mp.positionpath(name)
+ local w, h, d = getwhd(name)
+ if w then
+ fprint("((%p,%p)--(%p,%p)--(%p,%p)--(%p,%p)--cycle)",0,-d,w,-d,w,h,0,h)
+ else
+ mprint("(origin--cycle)")
+ end
+ end
+
+ function mp.positioncurve(name)
+ local w, h, d = getwhd(name)
+ if w then
+ fprint("((%p,%p)..(%p,%p)..(%p,%p)..(%p,%p)..cycle)",0,-d,w,-d,w,h,0,h)
+ else
+ mprint("(origin--cycle)")
+ end
+ end
+
+ function mp.positionbox(name)
+ local p, x, y, w, h, d = getposition(name)
+ if p then
+ fprint("((%p,%p)--(%p,%p)--(%p,%p)--(%p,%p)--cycle)",x,y-d,x+w,y-d,x+w,y+h,x,y+h)
+ else
+ mprint("(%p,%p)",x,y)
+ end
+ end
+
+ function mp.positionxy(name)
+ local x, y = getxy(name)
+ if x then
+ fprint("(%p,%p)",x,y)
+ else
+ mprint("origin")
+ end
+ end
+
+ function mp.positionpage(name)
+ local p = getpage(name)
+ if p then
+ fprint("%p",p)
+ else
+ mprint("0")
+ end
+ end
+
+ function mp.positionregion(name)
+ local r = getregion(name)
+ if r then
+ qprint(r)
+ else
+ qprint("unknown")
+ end
+ end
+
+ function mp.positionwhd(name)
+ local w, h, d = getwhd(name)
+ if w then
+ fprint("(%p,%p,%p)",w,h,d)
+ else
+ mprint("(0,0,0)")
+ end
+ end
+
+ function mp.positionpxy(name)
+ local p, x, y = getposition(name)
+ if p then
+ fprint("(%p,%p,%p)",p,x,y)
+ else
+ mprint("(0,0,0)")
+ end
+ end
+
+ function mp.positionanchor()
+ qprint(getmacro("MPanchorid"))
+ end
+
+end
diff --git a/tex/context/base/mkiv/mlib-pps.lua b/tex/context/base/mkiv/mlib-pps.lua
index d08d5ddb7..8c7910d16 100644
--- a/tex/context/base/mkiv/mlib-pps.lua
+++ b/tex/context/base/mkiv/mlib-pps.lua
@@ -13,9 +13,11 @@ local insert, remove, concat = table.insert, table.remove, table.concat
local Cs, Cf, C, Cg, Ct, P, S, V, Carg = lpeg.Cs, lpeg.Cf, lpeg.C, lpeg.Cg, lpeg.Ct, lpeg.P, lpeg.S, lpeg.V, lpeg.Carg
local lpegmatch, tsplitat, tsplitter = lpeg.match, lpeg.tsplitat, lpeg.tsplitter
local formatters = string.formatters
+local exists, savedata = io.exists, io.savedata
-local mplib, metapost, lpdf, context = mplib, metapost, lpdf, context
-
+local mplib = mplib
+local metapost = metapost
+local lpdf = lpdf
local context = context
local implement = interfaces.implement
@@ -761,11 +763,33 @@ implement {
arguments = "string"
}
+local pdftompy = sandbox.registerrunner {
+ name = "mpy:pstoedit",
+ program = "pstoedit",
+ template = "-ssp -dt -f mpost %pdffile% %mpyfile%",
+ checkers = {
+ pdffile = "writable",
+ mpyfile = "readable",
+ },
+ reporter = report_metapost,
+}
+
+local textopdf = sandbox.registerrunner {
+ name = "mpy:context",
+ program = "context",
+ template = "--once %runmode% %texfile%",
+ checkers = {
+ runmode = "string",
+ texfile = "readable",
+ },
+ reporter = report_metapost,
+}
+
function makempy.processgraphics(graphics)
if #graphics == 0 then
return
end
- if mpyfilename and io.exists(mpyfilename) then
+ if mpyfilename and exists(mpyfilename) then
report_metapost("using file: %s",mpyfilename)
return
end
@@ -775,16 +799,17 @@ function makempy.processgraphics(graphics)
local mpyfile = file.replacesuffix(mpofile,"mpy")
local pdffile = file.replacesuffix(mpofile,"pdf")
local texfile = file.replacesuffix(mpofile,"tex")
- io.savedata(texfile, { start, preamble, metapost.tex.get(), concat(graphics,"\n"), stop }, "\n")
- local command = format("context --once %s %s", (tex.interactionmode == 0 and "--batchmode") or "", texfile)
- os.execute(command)
- if io.exists(pdffile) then
- command = format("pstoedit -ssp -dt -f mpost %s %s", pdffile, mpyfile)
- logs.newline()
- report_metapost("running: %s",command)
- logs.newline()
- os.execute(command)
- if io.exists(mpyfile) then
+ savedata(texfile, { start, preamble, metapost.tex.get(), concat(graphics,"\n"), stop }, "\n")
+ textopdf {
+ runmode = tex.interactionmode == 0 and "--batchmode" or "",
+ texfile = texfile,
+ }
+ if exists(pdffile) then
+ pdftompy {
+ pdffile = pdffile,
+ mpyfile = mpyfile,
+ }
+ if exists(mpyfile) then
local result, r = { }, 0
local data = io.loaddata(mpyfile)
if data and #data > 0 then
@@ -792,7 +817,7 @@ function makempy.processgraphics(graphics)
r = r + 1
result[r] = formatters["begingraphictextfig%sendgraphictextfig ;\n"](figure)
end
- io.savedata(mpyfile,concat(result,""))
+ savedata(mpyfile,concat(result,""))
end
end
end
diff --git a/tex/context/base/mkiv/mult-def.lua b/tex/context/base/mkiv/mult-def.lua
index 69484a90f..7cee595cd 100644
--- a/tex/context/base/mkiv/mult-def.lua
+++ b/tex/context/base/mkiv/mult-def.lua
@@ -15238,6 +15238,9 @@ return {
["oldstyle"]={
["en"]="oldstyle",
},
+ ["fractions"]={
+ ["en"]="fractions",
+ },
["on"]={
["cs"]="zap",
["de"]="an",
diff --git a/tex/context/base/mkiv/mult-low.lua b/tex/context/base/mkiv/mult-low.lua
index ea1c169ea..23ee8688f 100644
--- a/tex/context/base/mkiv/mult-low.lua
+++ b/tex/context/base/mkiv/mult-low.lua
@@ -401,6 +401,7 @@ return {
"cldprocessfile", "cldloadfile", "cldcontext", "cldcommand",
--
"carryoverpar",
+ "lastlinewidth",
--
"assumelongusagecs",
--
diff --git a/tex/context/base/mkiv/mult-prm.lua b/tex/context/base/mkiv/mult-prm.lua
index 4f01b66b6..ef6a5a0ad 100644
--- a/tex/context/base/mkiv/mult-prm.lua
+++ b/tex/context/base/mkiv/mult-prm.lua
@@ -315,6 +315,7 @@ return {
"pdfvariable",
"postexhyphenchar",
"posthyphenchar",
+ "predisplaygapfactor",
"preexhyphenchar",
"prehyphenchar",
"primitive",
@@ -1139,6 +1140,7 @@ return {
"postexhyphenchar",
"posthyphenchar",
"predisplaydirection",
+ "predisplaygapfactor",
"predisplaypenalty",
"predisplaysize",
"preexhyphenchar",
diff --git a/tex/context/base/mkiv/mult-sys.mkiv b/tex/context/base/mkiv/mult-sys.mkiv
index 914929ab1..bd3ff9b3d 100644
--- a/tex/context/base/mkiv/mult-sys.mkiv
+++ b/tex/context/base/mkiv/mult-sys.mkiv
@@ -149,6 +149,7 @@
\definesystemconstant {sans}
\definesystemconstant {mono}
\definesystemconstant {math}
+\definesystemconstant {nomath}
\definesystemconstant {handwriting}
\definesystemconstant {calligraphy}
\definesystemconstant {casual}
@@ -358,7 +359,7 @@
\definesystemconstant {integral}
\definesystemconstant {insert} % maybe insertclass
\definesystemconstant {marker}
-
+\definesystemconstant {kernpairs}
\definesystemconstant {mixedcolumn}
%definesystemconstant {property}
diff --git a/tex/context/base/mkiv/node-acc.lua b/tex/context/base/mkiv/node-acc.lua
index a63aef646..dccd7b7c0 100644
--- a/tex/context/base/mkiv/node-acc.lua
+++ b/tex/context/base/mkiv/node-acc.lua
@@ -8,92 +8,72 @@ if not modules then modules = { } end modules ['node-acc'] = {
local nodes, node = nodes, node
-local nodecodes = nodes.nodecodes
-local tasks = nodes.tasks
-
-local nuts = nodes.nuts
-local tonut = nodes.tonut
-local tonode = nodes.tonode
-
-local getid = nuts.getid
-local getfield = nuts.getfield
-local getattr = nuts.getattr
-local getlist = nuts.getlist
-local getchar = nuts.getchar
-local getnext = nuts.getnext
-
-local setfield = nuts.setfield
-local setattr = nuts.setattr
-local setlink = nuts.setlink
-local setchar = nuts.setchar
-local setsubtype = nuts.setsubtype
-
------ traverse_nodes = nuts.traverse
-local traverse_id = nuts.traverse_id
-local copy_node = nuts.copy
-local flush_node_list = nuts.flush_list
-local insert_after = nuts.insert_after
-
-local glue_code = nodecodes.glue
------ kern_code = nodecodes.kern
-local glyph_code = nodecodes.glyph
-local hlist_code = nodecodes.hlist
-local vlist_code = nodecodes.vlist
-
-local a_characters = attributes.private("characters")
-
-local threshold = 65536 -- not used
-local nofreplaced = 0
+local nodecodes = nodes.nodecodes
+local tasks = nodes.tasks
+
+local nuts = nodes.nuts
+local tonut = nodes.tonut
+local tonode = nodes.tonode
+
+local getid = nuts.getid
+local getfield = nuts.getfield
+local getattr = nuts.getattr
+local getlist = nuts.getlist
+local getchar = nuts.getchar
+local getnext = nuts.getnext
+
+local setfield = nuts.setfield
+local setattr = nuts.setattr
+local setlink = nuts.setlink
+local setchar = nuts.setchar
+local setsubtype = nuts.setsubtype
+local getwidth = nuts.getwidth
+local setwidth = nuts.setwidth
+
+----- traverse_nodes = nuts.traverse
+local traverse_id = nuts.traverse_id
+----- copy_node = nuts.copy
+local insert_after = nuts.insert_after
+local copy_no_components = nuts.copy_no_components
+
+local glue_code = nodecodes.glue
+----- kern_code = nodecodes.kern
+local glyph_code = nodecodes.glyph
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+
+local a_characters = attributes.private("characters")
+
+local threshold = 65536 -- not used
+local nofreplaced = 0
-- todo: nbsp etc
--- todo: collapse kerns
-
--- p_id
+-- todo: collapse kerns (not needed, backend does this)
+-- todo: maybe cache as we now create many nodes
+-- todo: check for subtype related to spacing (13/14 but most seems to be user anyway)
local function injectspaces(head)
local p, p_id
local n = head
while n do
local id = getid(n)
- if id == glue_code then -- todo: check for subtype related to spacing (13/14 but most seems to be 0)
- -- if getfield(n,."width") > 0 then -- threshold
- -- if p and p_id == glyph_code then
+ if id == glue_code then
if p and getid(p) == glyph_code then
- local g = copy_node(p)
- local c = getfield(g,"components")
- if c then -- it happens that we copied a ligature
- flush_node_list(c)
- setfield(g,"components",nil)
- setsubtype(g,256)
- end
+ -- unless we don't care about the little bit of overhead
+ -- we can just: local g = copy_node(g)
+ local g = copy_no_components(p)
local a = getattr(n,a_characters)
setchar(g,32)
- setlink(p,g)
- setlink(g,n)
--- we could cache as we now create many nodes
- setfield(n,"width",getfield(n,"width") - getfield(g,"width"))
+ setlink(p,g,n)
+ setwidth(n,getwidth(n) - getwidth(g))
if a then
setattr(g,a_characters,a)
end
setattr(n,a_characters,0)
nofreplaced = nofreplaced + 1
end
- -- end
elseif id == hlist_code or id == vlist_code then
injectspaces(getlist(n),attribute)
- -- elseif id == kern_code then -- the backend already collapses
- -- local first = n
- -- while true do
- -- local nn = getnext(n)
- -- if nn and getid(nn) == kern_code then
- -- -- maybe we should delete kerns but who cares at this stage
- -- setfield(first,"kern",getfield(first,"kern") + getfield(nn,"kern")
- -- setfield(nn,"kern",0)
- -- n = nn
- -- else
- -- break
- -- end
- -- end
end
p_id = id
p = n
diff --git a/tex/context/base/mkiv/node-aux.lua b/tex/context/base/mkiv/node-aux.lua
index 7f2360276..c6b276337 100644
--- a/tex/context/base/mkiv/node-aux.lua
+++ b/tex/context/base/mkiv/node-aux.lua
@@ -35,6 +35,10 @@ local getfont = nuts.getfont
local getchar = nuts.getchar
local getattr = nuts.getattr
local getfield = nuts.getfield
+local getboth = nuts.getboth
+local getcomponents = nuts.getcomponents
+local getwidth = nuts.getwidth
+local setwidth = nuts.setwidth
local setfield = nuts.setfield
local setattr = nuts.setattr
@@ -42,18 +46,21 @@ local setlink = nuts.setlink
local setlist = nuts.setlist
local setnext = nuts.setnext
local setprev = nuts.setprev
+local setcomponents = nuts.setcomponents
+local setattrlist = nuts.setattrlist
local traverse_nodes = nuts.traverse
local traverse_id = nuts.traverse_id
local flush_node = nuts.flush
+local flush_list = nuts.flush_list
local hpack_nodes = nuts.hpack
local unset_attribute = nuts.unset_attribute
local first_glyph = nuts.first_glyph
local copy_node = nuts.copy
----- copy_node_list = nuts.copy_list
local find_tail = nuts.tail
-local insert_node_after = nuts.insert_after
local getbox = nuts.getbox
+local count = nuts.count
local nodepool = nuts.pool
local new_glue = nodepool.glue
@@ -341,11 +348,10 @@ local function tonodes(str,fnt,attr) -- (str,template_glyph) -- moved from blob-
n = new_glyph(fnt,s)
end
if attr then -- normally false when template
- -- setfield(n,"attr",copy_node_list(attr))
- setfield(n,"attr",attr)
+ setattrlist(n,attr)
end
if head then
- insert_node_after(head,tail,n)
+ setlink(tail,n)
else
head = n
end
@@ -447,9 +453,9 @@ end
local function rehpack(n,width)
local head = getlist(n)
- local size = width or getfield(n,"width")
+ local size = width or getwidth(n)
local temp = hpack_nodes(head,size,"exactly")
- setfield(n,"width", size)
+ setwidth(n,size)
setfield(n,"glue_set", getfield(temp,"glue_set"))
setfield(n,"glue_sign", getfield(temp,"glue_sign"))
setfield(n,"glue_order",getfield(temp,"glue_order"))
@@ -482,3 +488,177 @@ end
-- return 0
-- end
-- end
+
+-- these component helpers might move to another module
+
+-- nodemode helper: here we also flatten components, no check for disc here
+
+function nuts.set_components(target,start,stop)
+ local head = getcomponents(target)
+ if head then
+ flush_list(head)
+ head = nil
+ end
+ if start then
+ setprev(start)
+ else
+ return nil
+ end
+ if stop then
+ setnext(stop)
+ end
+ local tail = nil
+ while start do
+ local c = getcomponents(start)
+ local n = getnext(start)
+ if c then
+ if head then
+ setlink(tail,c)
+ else
+ head = c
+ end
+ tail = find_tail(c)
+ setcomponents(start)
+ flush_node(start)
+ else
+ if head then
+ setlink(tail,start)
+ else
+ head = start
+ end
+ tail = start
+ end
+ start = n
+ end
+ setcomponents(target,head)
+ -- maybe also upgrade the subtype but we don't use it anyway
+ return head
+end
+
+function nuts.get_components(target)
+ return getcomponents(target)
+end
+
+nuts.get_components = getcomponents
+
+function nuts.take_components(target)
+ local c = getcomponents(target)
+ setcomponents(target)
+ -- maybe also upgrade the subtype but we don't use it anyway
+ return c
+end
+
+-- nodemode helper: we assume a glyph and a flat components list (basemode can
+-- have nested components)
+
+function nuts.count_components(n,marks)
+ local components = getcomponents(n)
+ if components then
+ if marks then
+ local i = 0
+ for g in traverse_id(glyph_code,components) do
+ if not marks[getchar(g)] then
+ i = i + 1
+ end
+ end
+ return i
+ else
+ return count(glyph_code,components)
+ end
+ else
+ return 0
+ end
+end
+
+-- nodemode helper: the next and prev pointers are untouched
+
+function nuts.copy_no_components(g,copyinjection)
+ local components = getcomponents(g)
+ if components then
+ setcomponents(g)
+ local n = copy_node(g)
+ if copyinjection then
+ copyinjection(n,g)
+ end
+ setcomponents(g,components)
+ -- maybe also upgrade the subtype but we don't use it anyway
+ return n
+ else
+ local n = copy_node(g)
+ if copyinjection then
+ copyinjection(n,g)
+ end
+ return n
+ end
+end
+
+function nuts.copy_only_glyphs(current)
+ local head = nil
+ local previous = nil
+ for n in traverse_id(glyph_code,current) do
+ n = copy_node(n)
+ if head then
+ setlink(previous,n)
+ else
+ head = n
+ end
+ previous = n
+ end
+ return head
+end
+
+-- node- and basemode helper
+
+function nuts.use_components(head,current)
+ local components = getcomponents(current)
+ if not components then
+ return head, current, current
+ end
+ local prev, next = getboth(current)
+ local first = current
+ local last = next
+ while components do
+ local gone = current
+ local tail = find_tail(components)
+ if prev then
+ setlink(prev,components)
+ end
+ if next then
+ setlink(tail,next)
+ end
+ if first == current then
+ first = components
+ end
+ if head == current then
+ head = components
+ end
+ current = components
+ setcomponents(gone)
+ flush_node(gone)
+ while true do
+ components = getcomponents(current)
+ if components then
+ next = getnext(current)
+ break -- current is composed
+ end
+ if next == last then
+ last = current
+ break -- components is false
+ end
+ prev = current
+ current = next
+ next = getnext(current)
+ end
+ end
+ return head, first, last
+end
+
+-- function nuts.current_tail()
+-- local whatever = texnest[texnest.ptr]
+-- if whatever then
+-- local tail = whatever.tail
+-- if tail then
+-- return tonut(tail)
+-- end
+-- end
+-- end
diff --git a/tex/context/base/mkiv/node-bck.lua b/tex/context/base/mkiv/node-bck.lua
index 9ecc62170..abb025b74 100644
--- a/tex/context/base/mkiv/node-bck.lua
+++ b/tex/context/base/mkiv/node-bck.lua
@@ -11,7 +11,7 @@ if not modules then modules = { } end modules ['node-bck'] = {
local attributes, nodes, node = attributes, nodes, node
-local tasks = nodes.tasks
+local enableaction = nodes.tasks.enableaction
local nodecodes = nodes.nodecodes
local listcodes = nodes.listcodes
@@ -35,7 +35,6 @@ local getattr = nuts.getattr
local getsubtype = nuts.getsubtype
local getwhd = nuts.getwhd
-local setfield = nuts.setfield
local setattr = nuts.setattr
local setlink = nuts.setlink
local setlist = nuts.setlist
@@ -85,11 +84,12 @@ local function add_backgrounds(head) -- rather old code .. to be redone
if transparency then
setattr(rule,a_transparency,transparency)
end
- setlink(rule,glue)
- if list then
- setlink(glue,list)
- end
- setlist(current,rule)
+-- setlink(rule,glue)
+-- if list then
+-- setlink(glue,list)
+-- end
+-- setlist(current,rule)
+ setlist(current,rule,glue,list)
end
end
end
@@ -172,21 +172,16 @@ end
nodes.handlers.backgrounds = function(head) local head, done = add_backgrounds (tonut(head)) return tonode(head), done end
nodes.handlers.alignbackgrounds = function(head) local head, done = add_alignbackgrounds(tonut(head)) return tonode(head), done end
--- elsewhere: needs checking
-
--- tasks.appendaction("shipouts","normalizers","nodes.handlers.backgrounds")
--- tasks.appendaction("shipouts","normalizers","nodes.handlers.alignbackgrounds")
-
interfaces.implement {
name = "enablebackgroundboxes",
onlyonce = true,
- actions = nodes.tasks.enableaction,
+ actions = enableaction,
arguments = { "'shipouts'", "'nodes.handlers.backgrounds'" }
}
interfaces.implement {
name = "enablebackgroundalign",
onlyonce = true,
- actions = nodes.tasks.enableaction,
+ actions = enableaction,
arguments = { "'shipouts'", "'nodes.handlers.alignbackgrounds'" }
}
diff --git a/tex/context/base/mkiv/node-fin.lua b/tex/context/base/mkiv/node-fin.lua
index 25a2d2f44..03c8a7607 100644
--- a/tex/context/base/mkiv/node-fin.lua
+++ b/tex/context/base/mkiv/node-fin.lua
@@ -26,6 +26,7 @@ local getid = nuts.getid
local getlist = nuts.getlist
local getleader = nuts.getleader
local getattr = nuts.getattr
+local getwidth = nuts.getwidth
local setlist = nuts.setlist
local setleader = nuts.setleader
@@ -204,25 +205,31 @@ local function process(namespace,attribute,head,inheritance,default) -- one attr
if content ~= list then
setlist(stack,list)
end
- done = done or ok
+ if ok then
+ done = true
+ end
else
local list, ok = process(namespace,attribute,content,inheritance,default)
if content ~= list then
setlist(stack,list)
end
- done = done or ok
+ if ok then
+ done = true
+ end
end
else
local list, ok = process(namespace,attribute,content,inheritance,default)
if content ~= list then
setlist(stack,list)
end
- done = done or ok
+ if ok then
+ done = true
+ end
end
-- end nested --
end
elseif id == rule_code then
- check = getfield(stack,"width") ~= 0
+ check = getwidth(stack) ~= 0
end
-- much faster this way than using a check() and nested() function
if check then
@@ -230,14 +237,14 @@ local function process(namespace,attribute,head,inheritance,default) -- one attr
if c then
if default and c == inheritance then
if current ~= default then
- head = insert_node_before(head,stack,copied(nsdata[default]))
+ head = insert_node_before(head,stack,copied(nsdata[default]))
current = default
- done = true
+ done = true
end
elseif current ~= c then
- head = insert_node_before(head,stack,copied(nsdata[c]))
+ head = insert_node_before(head,stack,copied(nsdata[c]))
current = c
- done = true
+ done = true
end
if leader then
local savedcurrent = current
@@ -256,20 +263,26 @@ local function process(namespace,attribute,head,inheritance,default) -- one attr
if leader ~= list then
setleader(stack,list)
end
- done = done or ok
+ if ok then
+ done = true
+ end
else
local list, ok = process(namespace,attribute,leader,inheritance,default)
if leader ~= list then
setleader(stack,list)
end
- done = done or ok
+ if ok then
+ done = true
+ end
end
else
local list, ok = process(namespace,attribute,leader,inheritance,default)
if leader ~= list then
setleader(stack,list)
end
- done = done or ok
+ if ok then
+ done = true
+ end
end
-- end nested --
current = savedcurrent
@@ -277,14 +290,14 @@ local function process(namespace,attribute,head,inheritance,default) -- one attr
end
elseif default and inheritance then
if current ~= default then
- head = insert_node_before(head,stack,copied(nsdata[default]))
+ head = insert_node_before(head,stack,copied(nsdata[default]))
current = default
- done = true
+ done = true
end
elseif current > 0 then
- head = insert_node_before(head,stack,copied(nsnone))
+ head = insert_node_before(head,stack,copied(nsnone))
current = 0
- done = true
+ done = true
end
check = false
end
@@ -331,25 +344,31 @@ local function selective(namespace,attribute,head,inheritance,default) -- two at
if content ~= list then
setlist(stack,list)
end
- done = done or ok
+ if ok then
+ done = true
+ end
else
local list, ok = selective(namespace,attribute,content,inheritance,default)
if content ~= list then
setlist(stack,list)
end
- done = done or ok
+ if ok then
+ done = true
+ end
end
else
local list, ok = selective(namespace,attribute,content,inheritance,default)
if content ~= list then
setlist(stack,list)
end
- done = done or ok
+ if ok then
+ done = true
+ end
end
-- end nested
end
elseif id == rule_code then
- check = getfield(stack,"width") ~= 0
+ check = getwidth(stack) ~= 0
end
if check then
@@ -360,7 +379,9 @@ local function selective(namespace,attribute,head,inheritance,default) -- two at
local data = nsdata[default]
head = insert_node_before(head,stack,copied(data[nsforced or getattr(stack,nsselector) or nsselector]))
current = default
- done = true
+ if ok then
+ done = true
+ end
end
else
local s = getattr(stack,nsselector)
@@ -369,7 +390,9 @@ local function selective(namespace,attribute,head,inheritance,default) -- two at
head = insert_node_before(head,stack,copied(data[nsforced or getattr(stack,nsselector) or nsselector]))
current = c
current_selector = s
- done = true
+ if ok then
+ done = true
+ end
end
end
if leader then
@@ -381,20 +404,26 @@ local function selective(namespace,attribute,head,inheritance,default) -- two at
if leader ~= list then
setleader(stack,list)
end
- done = done or ok
+ if ok then
+ done = true
+ end
else
local list, ok = selective(namespace,attribute,leader,inheritance,default)
if leader ~= list then
setleader(stack,list)
end
- done = done or ok
+ if ok then
+ done = true
+ end
end
else
local list, ok = selective(namespace,attribute,leader,inheritance,default)
if leader ~= list then
setleader(stack,list)
end
- done = done or ok
+ if ok then
+ done = true
+ end
end
-- end nested
leader = false
@@ -402,9 +431,9 @@ local function selective(namespace,attribute,head,inheritance,default) -- two at
elseif default and inheritance then
if current ~= default then
local data = nsdata[default]
- head = insert_node_before(head,stack,copied(data[nsforced or getattr(stack,nsselector) or nsselector]))
+ head = insert_node_before(head,stack,copied(data[nsforced or getattr(stack,nsselector) or nsselector]))
current = default
- done = true
+ done = true
end
elseif current > 0 then
head = insert_node_before(head,stack,copied(nsnone))
@@ -456,55 +485,63 @@ local function stacked(namespace,attribute,head,default) -- no triggering, no in
if a and current ~= a and nslistwise[a] then -- viewerlayer / needs checking, see below
local p = current
current = a
- head = insert_node_before(head,stack,copied(nsdata[a]))
+ head = insert_node_before(head,stack,copied(nsdata[a]))
local list = stacked(namespace,attribute,content,current) -- two return values
if content ~= list then
setlist(stack,list)
end
- done = true
head, stack = insert_node_after(head,stack,copied(nsnone))
current = p
+ done = true
else
local list, ok = stacked(namespace,attribute,content,current)
if content ~= list then
setlist(stack,list) -- only if ok
end
- done = done or ok
+ if ok then
+ done = true
+ end
end
else
local list, ok = stacked(namespace,attribute,content,current)
if content ~= list then
setlist(stack,list) -- only if ok
end
- done = done or ok
+ if ok then
+ done = true
+ end
end
end
elseif id == rule_code then
- check = getfield(stack,"width") ~= 0
+ check = getwidth(stack) ~= 0
end
if check then
local a = getattr(stack,attribute)
if a then
if current ~= a then
- head = insert_node_before(head,stack,copied(nsdata[a]))
- depth = depth + 1
- current, done = a, true
+ head = insert_node_before(head,stack,copied(nsdata[a]))
+ depth = depth + 1
+ current = a
+ done = true
end
if leader then
local list, ok = stacked(namespace,attribute,content,current)
if leader ~= list then
setleader(stack,list) -- only if ok
end
- done = done or ok
+ if ok then
+ done = true
+ end
leader = false
end
elseif default > 0 then
--
elseif current > 0 then
- head = insert_node_before(head,stack,copied(nsnone))
- depth = depth - 1
- current, done = 0, true
+ head = insert_node_before(head,stack,copied(nsnone))
+ depth = depth - 1
+ current = 0
+ done = true
end
check = false
end
@@ -564,17 +601,21 @@ local function stacker(namespace,attribute,head,default) -- no triggering, no in
if content ~= list then
setlist(current,list)
end
- done = done or ok
+ if ok then
+ done = true
+ end
end
else
local list, ok = stacker(namespace,attribute,content,default)
if list ~= content then
setlist(current,list)
end
- done = done or ok
+ if ok then
+ done = true
+ end
end
elseif id == rule_code then
- check = getfield(current,"width") ~= 0
+ check = getwidth(current) ~= 0
end
if check then
@@ -588,11 +629,14 @@ local function stacker(namespace,attribute,head,default) -- no triggering, no in
if n then
head = insert_node_before(head,current,tonut(n)) -- a
end
- attrib, done = a, true
+ attrib = a
+ done = true
if leader then
-- tricky as a leader has to be a list so we cannot inject before
local list, ok = stacker(namespace,attribute,leader,attrib)
- done = done or ok
+ if ok then
+ done = true
+ end
leader = false
end
end
diff --git a/tex/context/base/mkiv/node-fnt.lua b/tex/context/base/mkiv/node-fnt.lua
index 60b1f8332..85525cac2 100644
--- a/tex/context/base/mkiv/node-fnt.lua
+++ b/tex/context/base/mkiv/node-fnt.lua
@@ -157,56 +157,75 @@ end
fonts.setdiscexpansion(true)
+local function start_trace(head)
+ run = run + 1
+ report_fonts()
+ report_fonts("checking node list, run %s",run)
+ report_fonts()
+ local n = tonut(head)
+ while n do
+ local char, id = isglyph(n)
+ if char then
+ local font = getfont(n)
+ local attr = getattr(n,0) or 0
+ report_fonts("font %03i, dynamic %03i, glyph %C",font,attr,char)
+ elseif id == disc_code then
+ report_fonts("[disc] %s",nodes.listtoutf(n,true,false,n))
+ elseif id == boundary_code then
+ report_fonts("[boundary] %i:%i",getsubtype(n),getfield(n,"value"))
+ else
+ report_fonts("[%s]",nodecodes[id])
+ end
+ n = getnext(n)
+ end
+end
+
+local function stop_trace(u,usedfonts,a,attrfonts,b,basefonts,r,redundant,e,expanders)
+ report_fonts()
+ report_fonts("statics : %s",u > 0 and concat(keys(usedfonts)," ") or "none")
+ report_fonts("dynamics: %s",a > 0 and concat(keys(attrfonts)," ") or "none")
+ report_fonts("built-in: %s",b > 0 and b or "none")
+ report_fonts("removed : %s",r > 0 and r or "none")
+if expanders then
+ report_fonts("expanded: %s",e > 0 and e or "none")
+end
+ report_fonts()
+end
+
function handlers.characters(head)
-- either next or not, but definitely no already processed list
starttiming(nodes)
- local usedfonts = { }
- local attrfonts = { }
- local basefonts = { }
- local a, u, b, r = 0, 0, 0, 0
- local basefont = nil
- local prevfont = nil
- local prevattr = 0
- local mode = nil
- local done = false
- local variants = nil
- local redundant = nil
+ local usedfonts = { }
+ local attrfonts = { }
+ local basefonts = { }
+ local basefont = nil
+ local prevfont = nil
+ local prevattr = 0
+ local done = false
+ local variants = nil
+ local redundant = nil
+ local none = false
+ local nuthead = tonut(head)
+
+ local a, u, b, r, e = 0, 0, 0, 0, 0
if trace_fontrun then
- run = run + 1
- report_fonts()
- report_fonts("checking node list, run %s",run)
- report_fonts()
- local n = tonut(head)
- while n do
- local char, id = isglyph(n)
- if char then
- local font = getfont(n)
- local attr = getattr(n,0) or 0
- report_fonts("font %03i, dynamic %03i, glyph %C",font,attr,char)
- elseif id == disc_code then
- report_fonts("[disc] %s",nodes.listtoutf(n,true,false,n))
- elseif id == boundary_code then
- report_fonts("[boundary] %i:%i",getsubtype(n),getfield(n,"value"))
- else
- report_fonts("[%s]",nodecodes[id])
- end
- n = getnext(n)
- end
+ start_trace(head)
end
- local nuthead = tonut(head)
+ -- There is no gain in checking for a single glyph and then having a fast path. On the
+ -- metafun manual (with some 2500 single char lists) the difference is just noise.
for n in traverse_char(nuthead) do
local font = getfont(n)
- local attr = getattr(n,0) or 0 -- zero attribute is reserved for fonts in context
+ local attr = (none and prevattr) or getattr(n,0) or 0 -- zero attribute is reserved for fonts in context
if font ~= prevfont or attr ~= prevattr then
prevfont = font
prevattr = attr
- mode = fontmodes[font] -- we can also avoid the attr check
variants = fontvariants[font]
- if mode == "none" then
+ none = fontmodes[font] == "none"
+ if none then
-- skip
-- variants = false
protect_glyph(n)
@@ -316,11 +335,17 @@ function handlers.characters(head)
if b > 0 then
for i=1,b do
local bi = basefonts[i]
- if r == bi[1] then
+ local b1 = bi[1]
+ local b2 = bi[2]
+ if b1 == b2 then
+ if b1 == r then
+ bi[1] = false
+ bi[2] = false
+ end
+ elseif b1 == r then
bi[1] = n
- end
- if r == bi[2] then
- bi[2] = n
+ elseif b2 == r then
+ bi[2] = p
end
end
end
@@ -328,26 +353,31 @@ function handlers.characters(head)
end
end
- local e = 0
-
if force_discrun then
-- basefont is not supported in disc only runs ... it would mean a lot of
-- ranges .. we could try to run basemode as a separate processor run but
-- not for now (we can consider it when the new node code is tested
- -- local prevfont = nil
- -- local prevattr = 0
-
for d in traverse_id(disc_code,nuthead) do
-- we could use first_glyph, only doing replace is good enough
local _, _, r = getdisc(d)
if r then
+ local prevfont = nil
+ local prevattr = nil
+ local none = false
for n in traverse_char(r) do
local font = getfont(n)
- local attr = getattr(n,0) or 0 -- zero attribute is reserved for fonts in context
+ local attr = (none and prevattr) or getattr(n,0) or 0 -- zero attribute is reserved for fonts in context
if font ~= prevfont or attr ~= prevattr then
- if attr > 0 then
+ prevfont = font
+ prevattr = attr
+ none = fontmodes[font] == "none" -- very unlikely that we run into disc nodes in none mode
+ if none then
+ -- skip
+ -- variants = false
+ protect_glyph(n)
+ elseif attr > 0 then
local used = attrfonts[font]
if not used then
used = { }
@@ -370,11 +400,11 @@ function handlers.characters(head)
end
end
end
- prevfont = font
- prevattr = attr
end
+ -- we assume one font for now (and if there are more and we get into issues then
+ -- we can always remove the break)
+ break
end
- break
elseif expanders then
local subtype = getsubtype(d)
if subtype == discretionary_code then
@@ -389,36 +419,35 @@ function handlers.characters(head)
end
if trace_fontrun then
- report_fonts()
- report_fonts("statics : %s",u > 0 and concat(keys(usedfonts)," ") or "none")
- report_fonts("dynamics: %s",a > 0 and concat(keys(attrfonts)," ") or "none")
- report_fonts("built-in: %s",b > 0 and b or "none")
- report_fonts("removed : %s",redundant and #redundant > 0 and #redundant or "none")
- if expanders then
- report_fonts("expanded: %s",e > 0 and e or "none")
- end
- report_fonts()
+ stop_trace(u,usedfonts,a,attrfonts,b,basefonts,r,redundant,e,expanders)
end
+
-- in context we always have at least 2 processors
if u == 0 then
-- skip
elseif u == 1 then
local font, processors = next(usedfonts)
- local attr = a == 0 and false or 0 -- 0 is the savest way
+ -- local attr = a == 0 and false or 0 -- 0 is the savest way
+ local attr = a > 0 and 0 or false -- 0 is the savest way
for i=1,#processors do
local h, d = processors[i](head,font,attr)
if d then
- head = h or head
+ if h then
+ head = h
+ end
done = true
end
end
else
- local attr = a == 0 and false or 0 -- 0 is the savest way
- for font, processors in next, usedfonts do
+ -- local attr = a == 0 and false or 0 -- 0 is the savest way
+ local attr = a > 0 and 0 or false -- 0 is the savest way
+ for font, processors in next, usedfonts do -- unordered
for i=1,#processors do
local h, d = processors[i](head,font,attr)
if d then
- head = h or head
+ if h then
+ head = h
+ end
done = true
end
end
@@ -428,22 +457,26 @@ function handlers.characters(head)
-- skip
elseif a == 1 then
local font, dynamics = next(attrfonts)
- for attribute, processors in next, dynamics do -- attr can switch in between
+ for attribute, processors in next, dynamics do -- unordered, attr can switch in between
for i=1,#processors do
local h, d = processors[i](head,font,attribute)
if d then
- head = h or head
+ if h then
+ head = h
+ end
done = true
end
end
end
else
for font, dynamics in next, attrfonts do
- for attribute, processors in next, dynamics do -- attr can switch in between
+ for attribute, processors in next, dynamics do -- unordered, attr can switch in between
for i=1,#processors do
local h, d = processors[i](head,font,attribute)
if d then
- head = h or head
+ if h then
+ head = h
+ end
done = true
end
end
@@ -460,14 +493,15 @@ function handlers.characters(head)
if (start or stop) and (start ~= stop) then
local front = nuthead == start
if stop then
- start, stop = ligaturing(start,stop)
- start, stop = kerning(start,stop)
+ start = ligaturing(start,stop)
+ start = kerning(start,stop)
elseif start then -- safeguard
start = ligaturing(start)
start = kerning(start)
end
- if front then
- head = tonode(start)
+ if front and nuthead ~= start then
+ -- nuthead = start
+ head = tonode(start)
end
end
else
@@ -476,26 +510,28 @@ function handlers.characters(head)
local range = basefonts[i]
local start = range[1]
local stop = range[2]
- if start then
+ if start then -- and start ~= stop but that seldom happens
local front = nuthead == start
- local prev, next
+ local prev = getprev(start)
+ local next = getnext(stop)
if stop then
- next = getnext(stop)
start, stop = ligaturing(start,stop)
start, stop = kerning(start,stop)
else
- prev = getprev(start)
start = ligaturing(start)
start = kerning(start)
end
+ -- is done automatically
if prev then
setlink(prev,start)
end
if next then
setlink(stop,next)
end
+ -- till here
if front and nuthead ~= start then
- head = tonode(nuthead)
+ nuthead = start
+ head = tonode(start)
end
end
end
diff --git a/tex/context/base/mkiv/node-ltp.lua b/tex/context/base/mkiv/node-ltp.lua
index 32b11267b..22a4799ad 100644
--- a/tex/context/base/mkiv/node-ltp.lua
+++ b/tex/context/base/mkiv/node-ltp.lua
@@ -21,6 +21,7 @@ if not modules then modules = { } end modules ['node-par'] = {
-- todo: check and improve protrusion
-- todo: arabic etc (we could use pretty large scales there) .. marks and cursive
-- todo: see: we need to check this with the latest patches to the tex kernel
+-- todo: adapt math glue spacing to new model (left/right)
-- todo: optimize a bit more (less par.*)
@@ -139,14 +140,13 @@ local sub, formatters = string.sub, string.formatters
local round, floor = math.round, math.floor
local insert, remove = table.insert, table.remove
-local fonts, nodes, node = fonts, nodes, node
+-- local fonts, nodes, node = fonts, nodes, node -- too many locals
local trace_basic = false trackers.register("builders.paragraphs.basic", function(v) trace_basic = v end)
local trace_lastlinefit = false trackers.register("builders.paragraphs.lastlinefit", function(v) trace_lastlinefit = v end)
local trace_adjusting = false trackers.register("builders.paragraphs.adjusting", function(v) trace_adjusting = v end)
local trace_protruding = false trackers.register("builders.paragraphs.protruding", function(v) trace_protruding = v end)
local trace_expansion = false trackers.register("builders.paragraphs.expansion", function(v) trace_expansion = v end)
-local trace_quality = false trackers.register("builders.paragraphs.quality", function(v) trace_quality = v end)
local report_parbuilders = logs.reporter("nodes","parbuilders")
----- report_hpackers = logs.reporter("nodes","hpackers")
@@ -207,7 +207,14 @@ local getattr = nuts.getattr
local getdisc = nuts.getdisc
local getglue = nuts.getglue
local getwhd = nuts.getwhd
-local setwhd = nuts.setwhd
+local getcomponents = nuts.getcomponents
+local getkern = nuts.getkern
+local getpenalty = nuts.getpenalty
+local getdir = nuts.getdir
+local getshift = nuts.getshift
+local getwidth = nuts.getwidth
+local getheight = nuts.getheight
+local getdepth = nuts.getdepth
local isglyph = nuts.isglyph
@@ -220,6 +227,13 @@ local setprev = nuts.setprev
local setdisc = nuts.setdisc
local setsubtype = nuts.setsubtype
local setglue = nuts.setglue
+local setwhd = nuts.setwhd
+local setkern = nuts.setkern
+local setdir = nuts.setdir
+local setshift = nuts.setshift
+local setwidth = nuts.setwidth
+----- getheight = nuts.getheight
+----- getdepth = nuts.getdepth
local slide_node_list = nuts.slide -- get rid of this, probably ok > 78.2
local find_tail = nuts.tail
@@ -233,8 +247,6 @@ local insert_node_after = nuts.insert_after
local insert_node_before = nuts.insert_before
local is_zero_glue = nuts.is_zero_glue
-local setnodecolor = nodes.tracers.colors.set
-
local nodepool = nuts.pool
local nodecodes = nodes.nodecodes
@@ -352,12 +364,12 @@ local function checked_line_dir(stack,current)
local n = stack.n + 1
stack.n = n
stack[n] = current
- return getfield(current,"dir")
+ return getdir(current)
elseif n > 0 then
local n = stack.n
local dirnode = stack[n]
dirstack.n = n - 1
- return getfield(dirnode,"dir")
+ return getdir(dirnode)
else
report_parbuilders("warning: missing pop node (%a)",1) -- in line ...
end
@@ -374,7 +386,7 @@ local function inject_dirs_at_end_of_line(stack,current,start,stop)
while start and start ~= stop do
local id = getid(start)
if id == dir_code then
- if not dir_pops[getfield(start,"dir")] then -- weird, what is this #
+ if not dir_pops[getdir(start)] then -- weird, what is this #
n = n + 1
stack[n] = start
elseif n > 0 then
@@ -386,7 +398,7 @@ local function inject_dirs_at_end_of_line(stack,current,start,stop)
start = getnext(start)
end
for i=n,1,-1 do
- h, current = insert_node_after(current,current,new_dir(dir_negations[getfield(stack[i],"dir")]))
+ h, current = insert_node_after(current,current,new_dir(dir_negations[getdir(stack[i])]))
end
stack.n = n
return current
@@ -754,13 +766,13 @@ local function add_to_width(line_break_dir,checked_expansion,s) -- split into tw
end
elseif id == hlist_code or id == vlist_code then
local wd, ht, dp = getwhd(s)
- if is_parallel[getfield(s,"dir")][line_break_dir] then
+ if is_parallel[getdir(s)][line_break_dir] then
size = size + wd
else
size = size + ht + dp
end
elseif id == kern_code then
- local kern = getfield(s,"kern")
+ local kern = getkern(s)
if kern ~= 0 then
if checked_expansion and expand_kerns and (getsubtype(s) == kerning_code or getattr(a_fontkern)) then
local stretch, shrink = kern_stretch_shrink(s,kern)
@@ -776,7 +788,7 @@ local function add_to_width(line_break_dir,checked_expansion,s) -- split into tw
size = size + kern
end
elseif id == rule_code then
- size = size + getfield(s,"width")
+ size = size + getwidth(s)
elseif trace_unsupported then
report_parbuilders("unsupported node at location %a",6)
end
@@ -831,12 +843,12 @@ local function compute_break_width(par,break_type,p) -- split in two
elseif id == kern_code then
local s = getsubtype(p)
if s == userkern_code or s == italickern_code then
- break_width.size = break_width.size - getfield(p,"kern")
+ break_width.size = break_width.size - getkern(p)
else
return
end
elseif id == math_code then
- break_width.size = break_width.size - getfield(p,"surround")
+ break_width.size = break_width.size - getkern(p) -- surround
-- new in luatex
local wd, stretch, shrink, stretch_order = getglue(p)
local order = stretch_orders[stretch_order]
@@ -859,7 +871,7 @@ local function append_to_vlist(par, b)
if prev_depth > ignore_depth then
if is_hlist then
local width, stretch, shrink, stretch_order, shrink_order = getglue(par.baseline_skip)
- local delta = width - prev_depth - getfield(b,"height") -- deficiency of space between baselines
+ local delta = width - prev_depth - getheight(b) -- deficiency of space between baselines
local skip = nil
if delta < par.line_skip_limit then
width, stretch, shrink, stretch_order, shrink_order = getglue(par.lineskip)
@@ -882,7 +894,7 @@ local function append_to_vlist(par, b)
par.head_field = b
end
if is_hlist then
- local pd = getfield(b,"depth")
+ local pd = getdepth(b)
par.prev_depth = pd
texnest[texnest.ptr].prevdepth = pd
end
@@ -1303,9 +1315,9 @@ local function post_line_break(par)
setdisc(lastnode) -- nil, nil, nil
disc_break = true
elseif id == kern_code then
- setfield(lastnode,"kern",0)
+ setkern(lastnode,0)
elseif getid(lastnode) == math_code then
- setfield(lastnode,"surround",0)
+ setkern(lastnode,0) -- surround
-- new in luatex
setglue(lastnode) -- zeros
end
@@ -1398,21 +1410,21 @@ local function post_line_break(par)
local adjust_head = texlists.adjust_head
local pre_adjust_head = texlists.pre_adjust_head
--
- setfield(finished_line,"shift",cur_indent)
+ setshift(finished_line,cur_indent)
--
-- -- this is gone:
--
-- if par.each_line_height ~= ignored_dimen then
- -- setfield(finished_line,"height",par.each_line_height)
+ -- setheight(finished_line,par.each_line_height)
-- end
-- if par.each_line_depth ~= ignored_dimen then
- -- setfield(finished_line,"depth",par.each_line_depth)
+ -- setdepth(finished_line,par.each_line_depth)
-- end
-- if par.first_line_height ~= ignored_dimen and (current_line == par.first_line + 1) then
- -- setfield(finished_line,"height",par.first_line_height)
+ -- setheight(finished_line,par.first_line_height)
-- end
-- if par.last_line_depth ~= ignored_dimen and current_line + 1 == par.best_line then
- -- setfield(finished_line,"depth",par.last_line_depth)
+ -- setdepth(finished_line,par.last_line_depth)
-- end
--
if texlists.pre_adjust_head ~= pre_adjust_head then
@@ -1473,7 +1485,7 @@ local function post_line_break(par)
break
elseif id == math_code then
-- keep the math node
- setfield(next,"surround",0)
+ setkern(next,0) -- surround
-- new in luatex
setglue(lastnode) -- zeros
break
@@ -1519,7 +1531,7 @@ local function wrap_up(par)
par.do_last_line_fit = false
else
local glue = par.final_par_glue
- setfield(glue,"width",getfield(glue,"width") + active_short - active_glue)
+ setwidth(glue,getwidth(glue) + active_short - active_glue)
setfield(glue,"stretch",0)
if trace_lastlinefit then
report_parbuilders("applying last line fit, short %a, glue %p",active_short,active_glue)
@@ -2263,7 +2275,7 @@ function constructors.methods.basic(head,d)
end
elseif id == hlist_code or id == vlist_code then
local wd, ht, dp = getwhd(current)
- if is_parallel[getfield(current,"dir")][par.line_break_dir] then
+ if is_parallel[getdir(current)][par.line_break_dir] then
active_width.size = active_width.size + wd
else
active_width.size = active_width.size + ht + dp
@@ -2298,7 +2310,7 @@ function constructors.methods.basic(head,d)
if second_pass or subtype <= automatic_disc_code then
local actual_pen = subtype == automatic_disc_code and par.ex_hyphen_penalty or par.hyphen_penalty
-- 0.81 :
- -- local actual_pen = getfield(current,"penalty")
+ -- local actual_pen = getpenalty(current)
--
local pre, post, replace = getdisc(current)
if not pre then -- trivial pre-break
@@ -2377,9 +2389,9 @@ function constructors.methods.basic(head,d)
p_active, n_active = try_break(0, unhyphenated_code, par, first_p, current, checked_expansion)
end
local active_width = par.active_width
- active_width.size = active_width.size + getfield(current,"kern")
+ active_width.size = active_width.size + getkern(current)
else
- local kern = getfield(current,"kern")
+ local kern = getkern(current)
if kern ~= 0 then
active_width.size = active_width.size + kern
if checked_expansion and expand_kerns and (getsubtype(current) == kerning_code or getattr(current,a_fontkern)) then
@@ -2404,13 +2416,13 @@ function constructors.methods.basic(head,d)
p_active, n_active = try_break(0, unhyphenated_code, par, first_p, current, checked_expansion)
end
local active_width = par.active_width
- active_width.size = active_width.size + getfield(current,"surround")
+ active_width.size = active_width.size + getkern(current) -- surround
-- new in luatex
- + getfield(current,"width")
+ + getwidth(current)
elseif id == rule_code then
- active_width.size = active_width.size + getfield(current,"width")
+ active_width.size = active_width.size + getwidth(current)
elseif id == penalty_code then
- p_active, n_active = try_break(getfield(current,"penalty"), unhyphenated_code, par, first_p, current, checked_expansion)
+ p_active, n_active = try_break(getpenalty(current), unhyphenated_code, par, first_p, current, checked_expansion)
elseif id == dir_code then
par.line_break_dir = checked_line_dir(dirstack) or par.line_break_dir
elseif id == localpar_code then
@@ -2492,144 +2504,190 @@ end
-- standard tex logging .. will be adapted ..
-local function write_esc(cs)
- local esc = tex.escapechar
- if esc then
- write("log",utfchar(esc),cs)
- else
- write("log",cs)
+do
+
+ local function write_esc(cs)
+ local esc = tex.escapechar
+ if esc then
+ write("log",utfchar(esc),cs)
+ else
+ write("log",cs)
+ end
end
-end
-function diagnostics.start()
-end
+ function diagnostics.start()
+ end
-function diagnostics.stop()
- write_nl("log",'')
-end
+ function diagnostics.stop()
+ write_nl("log",'')
+ end
-function diagnostics.current_pass(par,what)
- write_nl("log",formatters["@%s"](what))
-end
+ function diagnostics.current_pass(par,what)
+ write_nl("log",formatters["@%s"](what))
+ end
-local verbose = false -- true
+ local verbose = false -- true
-local function short_display(target,a,font_in_short_display)
- while a do
- local char, id = isglyph(a)
- if char then
- local font = getfont(a)
- if font ~= font_in_short_display then
- write(target,tex.fontidentifier(font) .. ' ')
- font_in_short_display = font
- end
- if getsubtype(a) == ligature_code then
- font_in_short_display = short_display(target,getfield(a,"components"),font_in_short_display)
- else
- write(target,utfchar(char))
- end
- elseif id == disc_code then
- local pre, post, replace = getdisc(a)
- font_in_short_display = short_display(target,pre,font_in_short_display)
- font_in_short_display = short_display(target,post,font_in_short_display)
- elseif verbose then
- write(target,formatters["[%s]"](nodecodes[id]))
- elseif id == rule_code then
- write(target,"|")
- elseif id == glue_code then
- write(target," ")
- elseif id == kern_code then
- local s = getsubtype(a)
- if s == userkern_code or s == italickern_code or getattr(a,a_fontkern) then
- if verbose then
- write(target,"[|]")
- -- else
- -- write(target,"")
+ local function short_display(target,a,font_in_short_display)
+ while a do
+ local char, id = isglyph(a)
+ if char then
+ local font = getfont(a)
+ if font ~= font_in_short_display then
+ write(target,tex.fontidentifier(font) .. ' ')
+ font_in_short_display = font
+ end
+ -- todo: instead of components the split tounicode string
+ if getsubtype(a) == ligature_code then
+ font_in_short_display = short_display(target,getcomponents(a),font_in_short_display)
+ else
+ write(target,utfchar(char))
+ end
+ elseif id == disc_code then
+ local pre, post, replace = getdisc(a)
+ font_in_short_display = short_display(target,pre,font_in_short_display)
+ font_in_short_display = short_display(target,post,font_in_short_display)
+ elseif verbose then
+ write(target,formatters["[%s]"](nodecodes[id]))
+ elseif id == rule_code then
+ write(target,"|")
+ elseif id == glue_code then
+ write(target," ")
+ elseif id == kern_code then
+ local s = getsubtype(a)
+ if s == userkern_code or s == italickern_code or getattr(a,a_fontkern) then
+ if verbose then
+ write(target,"[|]")
+ -- else
+ -- write(target,"")
+ end
+ else
+ write(target,"[]")
end
+ elseif id == math_code then
+ write(target,"$")
else
write(target,"[]")
end
- elseif id == math_code then
- write(target,"$")
- else
- write(target,"[]")
+ a = getnext(a)
end
- a = getnext(a)
+ return font_in_short_display
end
- return font_in_short_display
-end
-diagnostics.short_display = short_display
+ diagnostics.short_display = short_display
-function diagnostics.break_node(par, q, fit_class, break_type, current) -- %d ?
- local passive = par.passive
- local typ_ind = break_type == hyphenated_code and '-' or ""
- if par.do_last_line_fit then
- local s = number.toscaled(q.active_short)
- local g = number.toscaled(q.active_glue)
- if current then
- write_nl("log",formatters["@@%d: line %d.%d%s t=%s s=%s g=%s"](
- passive.serial or 0,q.line_number-1,fit_class,typ_ind,q.total_demerits,s,g))
+ function diagnostics.break_node(par, q, fit_class, break_type, current) -- %d ?
+ local passive = par.passive
+ local typ_ind = break_type == hyphenated_code and '-' or ""
+ if par.do_last_line_fit then
+ local s = number.toscaled(q.active_short)
+ local g = number.toscaled(q.active_glue)
+ if current then
+ write_nl("log",formatters["@@%d: line %d.%d%s t=%s s=%s g=%s"](
+ passive.serial or 0,q.line_number-1,fit_class,typ_ind,q.total_demerits,s,g))
+ else
+ write_nl("log",formatters["@@%d: line %d.%d%s t=%s s=%s a=%s"](
+ passive.serial or 0,q.line_number-1,fit_class,typ_ind,q.total_demerits,s,g))
+ end
else
- write_nl("log",formatters["@@%d: line %d.%d%s t=%s s=%s a=%s"](
- passive.serial or 0,q.line_number-1,fit_class,typ_ind,q.total_demerits,s,g))
+ write_nl("log",formatters["@@%d: line %d.%d%s t=%s"](
+ passive.serial or 0,q.line_number-1,fit_class,typ_ind,q.total_demerits))
+ end
+ if not passive.prev_break then
+ write("log"," -> @0")
+ else
+ write("log",formatters[" -> @%d"](passive.prev_break.serial or 0))
end
- else
- write_nl("log",formatters["@@%d: line %d.%d%s t=%s"](
- passive.serial or 0,q.line_number-1,fit_class,typ_ind,q.total_demerits))
- end
- if not passive.prev_break then
- write("log"," -> @0")
- else
- write("log",formatters[" -> @%d"](passive.prev_break.serial or 0))
end
-end
-function diagnostics.feasible_break(par, current, r, b, pi, d, artificial_demerits)
- local printed_node = par.printed_node
- if printed_node ~= current then
- write_nl("log","")
+ function diagnostics.feasible_break(par, current, r, b, pi, d, artificial_demerits)
+ local printed_node = par.printed_node
+ if printed_node ~= current then
+ write_nl("log","")
+ if not current then
+ par.font_in_short_display = short_display("log",getnext(printed_node),par.font_in_short_display)
+ else
+ local save_link = getnext(current)
+ setnext(current)
+ write_nl("log","")
+ par.font_in_short_display = short_display("log",getnext(printed_node),par.font_in_short_display)
+ setnext(current,save_link)
+ end
+ par.printed_node = current
+ end
+ write_nl("log","@")
if not current then
- par.font_in_short_display = short_display("log",getnext(printed_node),par.font_in_short_display)
+ write_esc("par")
else
- local save_link = getnext(current)
- setnext(current)
- write_nl("log","")
- par.font_in_short_display = short_display("log",getnext(printed_node),par.font_in_short_display)
- setnext(current,save_link)
+ local id = getid(current)
+ if id == glue_code then
+ -- print nothing
+ elseif id == penalty_code then
+ write_esc("penalty")
+ elseif id == disc_code then
+ write_esc("discretionary")
+ elseif id == kern_code then
+ write_esc("kern")
+ elseif id == math_code then
+ write_esc("math")
+ else
+ write_esc("unknown")
+ end
+ end
+ local via, badness, demerits = 0, '*', '*'
+ if r.break_node then
+ via = r.break_node.serial or 0
+ end
+ if b <= infinite_badness then
+ badness = tonumber(d)
+ end
+ if not artificial_demerits then
+ demerits = tonumber(d)
end
- par.printed_node = current
+ write("log",formatters[" via @%d b=%s p=%s d=%s"](via,badness,pi,demerits))
end
- write_nl("log","@")
- if not current then
- write_esc("par")
- else
- local id = getid(current)
- if id == glue_code then
- -- print nothing
- elseif id == penalty_code then
- write_esc("penalty")
- elseif id == disc_code then
- write_esc("discretionary")
- elseif id == kern_code then
- write_esc("kern")
- elseif id == math_code then
- write_esc("math")
+
+ --
+
+ local function common_message(hlist,line,str)
+ write_nl("")
+ if status.output_active then -- unset
+ write(str," has occurred while \\output is active")
+ else
+ write(str)
+ end
+ local fileline = status.linenumber
+ if line > 0 then
+ write(formatters[" in paragraph at lines %s--%s"](fileline,"--",fileline+line-1))
+ elseif line < 0 then
+ write(formatters[" in alignment at lines "](fileline,"--",fileline-line-1))
else
- write_esc("unknown")
+ write(formatters[" detected at line %s"](fileline))
end
+ write_nl("")
+ diagnostics.short_display(getlist(hlist),false)
+ write_nl("")
+ -- diagnostics.start()
+ -- show_box(getlist(hlist))
+ -- diagnostics.stop()
+ end
+
+ function diagnostics.overfull_hbox(hlist,line,d)
+ common_message(hlist,line,formatters["Overfull \\hbox (%spt too wide)"](number.toscaled(d)))
end
- local via, badness, demerits = 0, '*', '*'
- if r.break_node then
- via = r.break_node.serial or 0
+
+ function diagnostics.bad_hbox(hlist,line,b)
+ common_message(hlist,line,formatters["Tight \\hbox (badness %i)"](b))
end
- if b <= infinite_badness then
- badness = tonumber(d)
+
+ function diagnostics.underfull_hbox(hlist,line,b)
+ common_message(hlist,line,formatters["Underfull \\hbox (badness %i)"](b))
end
- if not artificial_demerits then
- demerits = tonumber(d)
+
+ function diagnostics.loose_hbox(hlist,line,b)
+ common_message(hlist,line,formatters["Loose \\hbox (badness %i)"](b))
end
- write("log",formatters[" via @%d b=%s p=%s d=%s"](via,badness,pi,demerits))
+
end
-- reporting --
@@ -2640,574 +2698,536 @@ statistics.register("alternative parbuilders", function()
end
end)
--- actually scaling kerns is not such a good idea and it will become
--- configureable
-
--- This is no way a replacement for the built in (fast) packer
--- it's just an alternative for special (testing) purposes.
---
--- We could use two hpacks: one to be used in the par builder
--- and one to be used for other purposes. The one in the par
--- builder is much more simple as it does not need the expansion
--- code but only need to register the effective expansion factor
--- with the glyph.
-
-local function glyph_width_height_depth(curdir,pdir,p)
- local wd, ht, dp = getwhd(p)
- if is_rotated[curdir] then
- if is_parallel[curdir][pdir] then
- local half = (ht + dp) / 2
- return wd, half, half
- else
- local half = wd / 2
- return ht + dp, half, half
- end
- elseif is_rotated[pdir] then
- if is_parallel[curdir][pdir] then
- local half = (ht + dp) / 2
- return wd, half, half
+do
+
+ -- actually scaling kerns is not such a good idea and it will become
+ -- configureable
+
+ -- This is no way a replacement for the built in (fast) packer
+ -- it's just an alternative for special (testing) purposes.
+ --
+ -- We could use two hpacks: one to be used in the par builder
+ -- and one to be used for other purposes. The one in the par
+ -- builder is much more simple as it does not need the expansion
+ -- code but only need to register the effective expansion factor
+ -- with the glyph.
+
+ local setnodecolor = nodes.tracers.colors.set
+
+ local function glyph_width_height_depth(curdir,pdir,p)
+ local wd, ht, dp = getwhd(p)
+ if is_rotated[curdir] then
+ if is_parallel[curdir][pdir] then
+ local half = (ht + dp) / 2
+ return wd, half, half
+ else
+ local half = wd / 2
+ return ht + dp, half, half
+ end
+ elseif is_rotated[pdir] then
+ if is_parallel[curdir][pdir] then
+ local half = (ht + dp) / 2
+ return wd, half, half
+ else
+ return ht + dp, wd, 0 -- weird
+ end
else
- return ht + dp, wd, 0 -- weird
- end
- else
- if glyphdir_is_equal[curdir][pdir] then
- return wd, ht, dp
- elseif is_opposite[curdir][pdir] then
- return wd, dp, ht
- else -- can this happen?
- return ht + dp, wd, 0
+ if glyphdir_is_equal[curdir][pdir] then
+ return wd, ht, dp
+ elseif is_opposite[curdir][pdir] then
+ return wd, dp, ht
+ else -- can this happen?
+ return ht + dp, wd, 0
+ end
end
end
-end
-local function pack_width_height_depth(curdir,pdir,p)
- local wd, ht, dp = getwhd(p)
- if is_rotated[curdir] then
- if is_parallel[curdir][pdir] then
- local half = (ht + dp) / 2
- return wd, half, half
- else -- can this happen?
- local half = wd / 2
- return ht + dp, half, half
- end
- else
- if pardir_is_equal[curdir][pdir] then
- return wd, ht, dp
- elseif is_opposite[curdir][pdir] then
- return wd, dp, ht
- else -- weird dimensions, can this happen?
- return ht + dp, wd, 0
+ local function pack_width_height_depth(curdir,pdir,p)
+ local wd, ht, dp = getwhd(p)
+ if is_rotated[curdir] then
+ if is_parallel[curdir][pdir] then
+ local half = (ht + dp) / 2
+ return wd, half, half
+ else -- can this happen?
+ local half = wd / 2
+ return ht + dp, half, half
+ end
+ else
+ if pardir_is_equal[curdir][pdir] then
+ return wd, ht, dp
+ elseif is_opposite[curdir][pdir] then
+ return wd, dp, ht
+ else -- weird dimensions, can this happen?
+ return ht + dp, wd, 0
+ end
end
end
-end
--- local function xpack(head,width,method,direction,analysis)
---
--- -- inspect(analysis)
---
--- local expansion = method == "cal_expand_ratio"
--- local natural = analysis.size
--- local font_stretch = analysis.adjust_stretch
--- local font_shrink = analysis.adjust_shrink
--- local font_expand_ratio = 0
--- local delta = width - natural
---
--- local hlist = new_hlist()
---
--- setlist(hlist,head)
--- setfield(hlist,"dir",direction or tex.textdir)
--- setfield(hlist,"width",width)
--- setfield(hlist,"height",height)
--- setfield(hlist,"depth",depth)
---
--- if delta == 0 then
---
--- setfield(hlist,"glue_sign",0)
--- setfield(hlist,"glue_order",0)
--- setfield(hlist,"glue_set",0)
---
--- else
---
--- local order = analysis.filll ~= 0 and fillcodes.filll or
--- analysis.fill ~= 0 and fillcodes.fill or
--- analysis.fil ~= 0 and fillcodes.fil or
--- analysis.fi ~= 0 and fillcodes.fi or 0
---
--- if delta > 0 then
---
--- if expansion and order == 0 and font_stretch > 0 then
--- font_expand_ratio = (delta/font_stretch) * 1000
--- else
--- local stretch = analysis.stretch
--- if stretch ~= 0 then
--- setfield(hlist,"glue_sign",1) -- stretch
--- setfield(hlist,"glue_order",order)
--- setfield(hlist,"glue_set",delta/stretch)
--- else
--- setfield(hlist,"glue_sign",0) -- nothing
--- setfield(hlist,"glue_order",order)
--- setfield(hlist,"glue_set",0)
--- end
--- end
---
--- else
---
--- if expansion and order == 0 and font_shrink > 0 then
--- font_expand_ratio = (delta/font_shrink) * 1000
--- else
--- local shrink = analysis.shrink
--- if shrink ~= 0 then
--- setfield(hlist,"glue_sign",2) -- shrink
--- setfield(hlist,"glue_order",order)
--- setfield(hlist,"glue_set",-delta/stretch)
--- else
--- setfield(hlist,"glue_sign",0) -- nothing
--- setfield(hlist,"glue_order",order)
--- setfield(hlist,"glue_set",0)
--- end
--- end
---
--- end
---
--- end
---
--- if not expansion or font_expand_ratio == 0 then
--- -- nothing
--- elseif font_expand_ratio > 0 then
--- if font_expand_ratio > 1000 then
--- font_expand_ratio = 1000
--- end
--- local current = head
--- while current do
--- local id = getid(current)
--- if id == glyph_code then
--- local stretch, shrink = char_stretch_shrink(current) -- get only one
--- if stretch then
--- if trace_expansion then
--- setnodecolor(g,"hz:positive")
--- end
--- current.expansion_factor = font_expand_ratio * stretch
--- end
--- elseif id == kern_code then
--- local kern = getfield(current,"kern")
--- if kern ~= 0 and getsubtype(current) == kerning_code then
--- setfield(current,"kern",font_expand_ratio * kern)
--- end
--- end
--- current = getnext(current)
--- end
--- elseif font_expand_ratio < 0 then
--- if font_expand_ratio < -1000 then
--- font_expand_ratio = -1000
--- end
--- local current = head
--- while current do
--- local id = getid(current)
--- if id == glyph_code then
--- local stretch, shrink = char_stretch_shrink(current) -- get only one
--- if shrink then
--- if trace_expansion then
--- setnodecolor(g,"hz:negative")
--- end
--- current.expansion_factor = font_expand_ratio * shrink
--- end
--- elseif id == kern_code then
--- local kern = getfield(current,"kern")
--- if kern ~= 0 and getsubtype(current) == kerning_code then
--- setfield(current,"kern",font_expand_ratio * kern)
--- end
--- end
--- current = getnext(current)
--- end
--- end
--- return hlist, 0
--- end
-
-local function hpack(head,width,method,direction,firstline,line) -- fast version when head = nil
-
- -- we can pass the adjust_width and adjust_height so that we don't need to recalculate them but
- -- with the glue mess it's less trivial as we lack detail .. challenge
-
- local hlist = new_hlist()
-
- setfield(hlist,"dir",direction)
-
- if head == nil then
- setfield(hlist,"width",width)
- return hlist, 0
- else
- setlist(hlist,head)
- end
+ -- local function xpack(head,width,method,direction,analysis)
+ --
+ -- -- inspect(analysis)
+ --
+ -- local expansion = method == "cal_expand_ratio"
+ -- local natural = analysis.size
+ -- local font_stretch = analysis.adjust_stretch
+ -- local font_shrink = analysis.adjust_shrink
+ -- local font_expand_ratio = 0
+ -- local delta = width - natural
+ --
+ -- local hlist = new_hlist()
+ --
+ -- setlist(hlist,head)
+ -- setdir(hlist,direction or tex.textdir)
+ -- setwhd(hlist,width,height,depth)
+ --
+ -- if delta == 0 then
+ --
+ -- setfield(hlist,"glue_sign",0)
+ -- setfield(hlist,"glue_order",0)
+ -- setfield(hlist,"glue_set",0)
+ --
+ -- else
+ --
+ -- local order = analysis.filll ~= 0 and fillcodes.filll or
+ -- analysis.fill ~= 0 and fillcodes.fill or
+ -- analysis.fil ~= 0 and fillcodes.fil or
+ -- analysis.fi ~= 0 and fillcodes.fi or 0
+ --
+ -- if delta > 0 then
+ --
+ -- if expansion and order == 0 and font_stretch > 0 then
+ -- font_expand_ratio = (delta/font_stretch) * 1000
+ -- else
+ -- local stretch = analysis.stretch
+ -- if stretch ~= 0 then
+ -- setfield(hlist,"glue_sign",1) -- stretch
+ -- setfield(hlist,"glue_order",order)
+ -- setfield(hlist,"glue_set",delta/stretch)
+ -- else
+ -- setfield(hlist,"glue_sign",0) -- nothing
+ -- setfield(hlist,"glue_order",order)
+ -- setfield(hlist,"glue_set",0)
+ -- end
+ -- end
+ --
+ -- else
+ --
+ -- if expansion and order == 0 and font_shrink > 0 then
+ -- font_expand_ratio = (delta/font_shrink) * 1000
+ -- else
+ -- local shrink = analysis.shrink
+ -- if shrink ~= 0 then
+ -- setfield(hlist,"glue_sign",2) -- shrink
+ -- setfield(hlist,"glue_order",order)
+ -- setfield(hlist,"glue_set",-delta/stretch)
+ -- else
+ -- setfield(hlist,"glue_sign",0) -- nothing
+ -- setfield(hlist,"glue_order",order)
+ -- setfield(hlist,"glue_set",0)
+ -- end
+ -- end
+ --
+ -- end
+ --
+ -- end
+ --
+ -- if not expansion or font_expand_ratio == 0 then
+ -- -- nothing
+ -- elseif font_expand_ratio > 0 then
+ -- if font_expand_ratio > 1000 then
+ -- font_expand_ratio = 1000
+ -- end
+ -- local current = head
+ -- while current do
+ -- local id = getid(current)
+ -- if id == glyph_code then
+ -- local stretch, shrink = char_stretch_shrink(current) -- get only one
+ -- if stretch then
+ -- if trace_expansion then
+ -- setnodecolor(g,"hz:positive")
+ -- end
+ -- current.expansion_factor = font_expand_ratio * stretch
+ -- end
+ -- elseif id == kern_code then
+ -- local kern = getkern(current)
+ -- if kern ~= 0 and getsubtype(current) == kerning_code then
+ -- setkern(current,font_expand_ratio * kern)
+ -- end
+ -- end
+ -- current = getnext(current)
+ -- end
+ -- elseif font_expand_ratio < 0 then
+ -- if font_expand_ratio < -1000 then
+ -- font_expand_ratio = -1000
+ -- end
+ -- local current = head
+ -- while current do
+ -- local id = getid(current)
+ -- if id == glyph_code then
+ -- local stretch, shrink = char_stretch_shrink(current) -- get only one
+ -- if shrink then
+ -- if trace_expansion then
+ -- setnodecolor(g,"hz:negative")
+ -- end
+ -- current.expansion_factor = font_expand_ratio * shrink
+ -- end
+ -- elseif id == kern_code then
+ -- local kern = getkern(current)
+ -- if kern ~= 0 and getsubtype(current) == kerning_code then
+ -- setkern(current,font_expand_ratio * kern)
+ -- end
+ -- end
+ -- current = getnext(current)
+ -- end
+ -- end
+ -- return hlist, 0
+ -- end
+
+ local function hpack(head,width,method,direction,firstline,line) -- fast version when head = nil
+
+ -- we can pass the adjust_width and adjust_height so that we don't need to recalculate them but
+ -- with the glue mess it's less trivial as we lack detail .. challenge
+
+ local hlist = new_hlist()
+
+ setdir(hlist,direction)
+
+ if head == nil then
+ setwidth(hlist,width)
+ return hlist, 0
+ else
+ setlist(hlist,head)
+ end
- local cal_expand_ratio = method == "cal_expand_ratio" or method == "subst_ex_font"
+ local cal_expand_ratio = method == "cal_expand_ratio" or method == "subst_ex_font"
- direction = direction or tex.textdir
+ direction = direction or tex.textdir
- local line = 0
+ local line = 0
- local height = 0
- local depth = 0
- local natural = 0
- local font_stretch = 0
- local font_shrink = 0
- local font_expand_ratio = 0
- local last_badness = 0
- local expansion_stack = cal_expand_ratio and { } -- todo: optionally pass this
- local expansion_index = 0
- local total_stretch = { [0] = 0, 0, 0, 0, 0 }
- local total_shrink = { [0] = 0, 0, 0, 0, 0 }
+ local height = 0
+ local depth = 0
+ local natural = 0
+ local font_stretch = 0
+ local font_shrink = 0
+ local font_expand_ratio = 0
+ local last_badness = 0
+ local expansion_stack = cal_expand_ratio and { } -- todo: optionally pass this
+ local expansion_index = 0
+ local total_stretch = { [0] = 0, 0, 0, 0, 0 }
+ local total_shrink = { [0] = 0, 0, 0, 0, 0 }
- local hpack_dir = direction
+ local hpack_dir = direction
- local adjust_head = texlists.adjust_head
- local pre_adjust_head = texlists.pre_adjust_head
- local adjust_tail = adjust_head and slide_node_list(adjust_head) -- todo: find_tail
- local pre_adjust_tail = pre_adjust_head and slide_node_list(pre_adjust_head) -- todo: find_tail
+ local adjust_head = texlists.adjust_head
+ local pre_adjust_head = texlists.pre_adjust_head
+ local adjust_tail = adjust_head and slide_node_list(adjust_head) -- todo: find_tail
+ local pre_adjust_tail = pre_adjust_head and slide_node_list(pre_adjust_head) -- todo: find_tail
- new_dir_stack(hpack_dir)
+ new_dir_stack(hpack_dir)
- local checked_expansion = false
+ local checked_expansion = false
- if cal_expand_ratio then
- checked_expansion = { }
- setmetatableindex(checked_expansion,check_expand_lines)
- end
+ if cal_expand_ratio then
+ checked_expansion = { }
+ setmetatableindex(checked_expansion,check_expand_lines)
+ end
- -- this one also needs to check the font, so in the end indeed we might end up with two variants
+ -- this one also needs to check the font, so in the end indeed we might end up with two variants
- local fontexps, lastfont
+ local fontexps, lastfont
- local function process(current) -- called nested in disc replace
+ local function process(current) -- called nested in disc replace
- while current do
- local char, id = isglyph(current)
- if char then
- if cal_expand_ratio then
- local currentfont = getfont(current)
- if currentfont ~= lastfont then
- fontexps = checked_expansion[currentfont] -- a bit redundant for the par line packer
- lastfont = currentfont
+ while current do
+ local char, id = isglyph(current)
+ if char then
+ if cal_expand_ratio then
+ local currentfont = getfont(current)
+ if currentfont ~= lastfont then
+ fontexps = checked_expansion[currentfont] -- a bit redundant for the par line packer
+ lastfont = currentfont
+ end
+ if fontexps then
+ local expansion = fontexps[char]
+ if expansion then
+ font_stretch = font_stretch + expansion.glyphstretch
+ font_shrink = font_shrink + expansion.glyphshrink
+ expansion_index = expansion_index + 1
+ expansion_stack[expansion_index] = current
+ end
+ end
+ end
+ -- use inline
+ local wd, ht, dp = glyph_width_height_depth(hpack_dir,"TLT",current) -- was TRT ?
+ natural = natural + wd
+ if ht > height then
+ height = ht
+ end
+ if dp > depth then
+ depth = dp
end
- if fontexps then
- local expansion = fontexps[char]
- if expansion then
- font_stretch = font_stretch + expansion.glyphstretch
- font_shrink = font_shrink + expansion.glyphshrink
+ elseif id == kern_code then
+ local kern = getkern(current)
+ if kern == 0 then
+ -- no kern
+ elseif getsubtype(current) == kerning_code then -- check getkern(p)
+ if cal_expand_ratio then
+ local stretch, shrink = kern_stretch_shrink(current,kern)
+ font_stretch = font_stretch + stretch
+ font_shrink = font_shrink + shrink
expansion_index = expansion_index + 1
expansion_stack[expansion_index] = current
end
+ natural = natural + kern
+ else
+ natural = natural + kern
end
- end
- -- use inline
- local wd, ht, dp = glyph_width_height_depth(hpack_dir,"TLT",current) -- was TRT ?
- natural = natural + wd
- if ht > height then
- height = ht
- end
- if dp > depth then
- depth = dp
- end
- elseif id == kern_code then
- local kern = getfield(current,"kern")
- if kern == 0 then
- -- no kern
- elseif getsubtype(current) == kerning_code then -- check getfield(p,"kern")
- if cal_expand_ratio then
- local stretch, shrink = kern_stretch_shrink(current,kern)
- font_stretch = font_stretch + stretch
- font_shrink = font_shrink + shrink
- expansion_index = expansion_index + 1
- expansion_stack[expansion_index] = current
+ elseif id == disc_code then
+ local subtype = getsubtype(current)
+ if subtype ~= second_disc_code then
+ -- todo : local stretch, shrink = char_stretch_shrink(s)
+ local replace = getfield(current,"replace")
+ if replace then
+ process(replace)
+ end
end
- natural = natural + kern
- else
- natural = natural + kern
- end
- elseif id == disc_code then
- local subtype = getsubtype(current)
- if subtype ~= second_disc_code then
- -- todo : local stretch, shrink = char_stretch_shrink(s)
- local replace = getfield(current,"replace")
- if replace then
- process(replace)
+ elseif id == glue_code then
+ local wd, stretch, shrink, stretch_order, shrink_order = getglue(current)
+ natural = natural + wd
+ total_stretch[stretch_order] = total_stretch[stretch_order] + stretch
+ total_shrink [shrink_order] = total_shrink[shrink_order] + shrink
+ if getsubtype(current) >= leaders_code then
+ local leader = getleader(current)
+ local wd, ht, dp = getwhd(leader) -- can become getwhd(current) after 1.003
+ if ht > height then
+ height = ht
+ end
+ if dp > depth then
+ depth = dp
+ end
end
- end
- elseif id == glue_code then
- local wd, stretch, shrink, stretch_order, shrink_order = getglue(current)
- natural = natural + wd
- total_stretch[stretch_order] = total_stretch[stretch_order] + stretch
- total_shrink [shrink_order] = total_shrink[shrink_order] + shrink
- if getsubtype(current) >= leaders_code then
- local leader = getleader(current)
- local ht = getfield(leader,"height")
- local dp = getfield(leader,"depth")
+ elseif id == hlist_code or id == vlist_code then
+ local sh = getshift(current)
+ local wd, ht, dp = pack_width_height_depth(hpack_dir,getdir(current) or hpack_dir,current) -- added: or pack_dir
+ local hs, ds = ht - sh, dp + sh
+ natural = natural + wd
+ if hs > height then
+ height = hs
+ end
+ if ds > depth then
+ depth = ds
+ end
+ elseif id == rule_code then
+ local wd, ht, dp = getwhd(current)
+ natural = natural + wd
if ht > height then
height = ht
end
if dp > depth then
depth = dp
end
+ elseif id == math_code then
+ natural = natural + getkern(current) -- surround
+ -- new in luatex
+ + getwidth(current)
+ elseif id == unset_code then
+ local wd, ht, dp = getwhd(current)
+ local sh = getshift(current)
+ local hs = ht - sh
+ local ds = dp + sh
+ natural = natural + wd
+ if hs > height then
+ height = hs
+ end
+ if ds > depth then
+ depth = ds
+ end
+ elseif id == ins_code or id == mark_code then
+ local prev, next = getboth(current)
+ if adjust_tail then -- todo
+ setlink(prev,next)
+ setlink(adjust_tail,current)
+ setnext(current)
+ adjust_tail = current
+ else
+ adjust_head = current
+ adjust_tail = current
+ setboth(current)
+ end
+ elseif id == adjust_code then
+ local list = getlist(current)
+ if adjust_tail then
+ setnext(adjust_tail,list)
+ else
+ adjust_head = list
+ end
+ adjust_tail = slide_node_list(list) -- find_tail(list)
+ elseif id == dir_code then
+ hpack_dir = checked_line_dir(stack,current) or hpack_dir
+ elseif id == marginkern_code then
+ local width = getwidth(current)
+ if cal_expand_ratio then
+ -- is this ok?
+ local glyph = getfield(current,"glyph")
+ local char_pw = getsubtype(current) == leftmargin_code and left_pw or right_pw
+ font_stretch = font_stretch - width - char_pw(glyph)
+ font_shrink = font_shrink - width - char_pw(glyph)
+ expansion_index = expansion_index + 1
+ expansion_stack[expansion_index] = glyph
+ end
+ natural = natural + width
end
- elseif id == hlist_code or id == vlist_code then
- local sh = getfield(current,"shift")
- local wd, ht, dp = pack_width_height_depth(hpack_dir,getfield(current,"dir") or hpack_dir,current) -- added: or pack_dir
- local hs, ds = ht - sh, dp + sh
- natural = natural + wd
- if hs > height then
- height = hs
- end
- if ds > depth then
- depth = ds
- end
- elseif id == rule_code then
- local wd, ht, dp = getwhd(current)
- natural = natural + wd
- if ht > height then
- height = ht
- end
- if dp > depth then
- depth = dp
- end
- elseif id == math_code then
- natural = natural + getfield(current,"surround")
- -- new in luatex
- + getfield(current,"width")
- elseif id == unset_code then
- local wd = getfield(current,"width")
- local ht = getfield(current,"height")
- local dp = getfield(current,"depth")
- local sh = getfield(current,"shift")
- local hs = ht - sh
- local ds = dp + sh
- natural = natural + wd
- if hs > height then
- height = hs
- end
- if ds > depth then
- depth = ds
- end
- elseif id == ins_code or id == mark_code then
- local prev, next = getboth(current)
- if adjust_tail then -- todo
- setlink(prev,next)
- setlink(adjust_tail,current)
- setnext(current)
- adjust_tail = current
- else
- adjust_head = current
- adjust_tail = current
- setboth(current)
- end
- elseif id == adjust_code then
- local list = getlist(current)
- if adjust_tail then
- setnext(adjust_tail,list)
- else
- adjust_head = list
- end
- adjust_tail = slide_node_list(list) -- find_tail(list)
- elseif id == dir_code then
- hpack_dir = checked_line_dir(stack,current) or hpack_dir
- elseif id == marginkern_code then
- local width = getfield(current,"width")
- if cal_expand_ratio then
- -- is this ok?
- local glyph = getfield(current,"glyph")
- local char_pw = getsubtype(current) == leftmargin_code and left_pw or right_pw
- font_stretch = font_stretch - width - char_pw(glyph)
- font_shrink = font_shrink - width - char_pw(glyph)
- expansion_index = expansion_index + 1
- expansion_stack[expansion_index] = glyph
- end
- natural = natural + width
+ current = getnext(current)
end
- current = getnext(current)
- end
- end
-
- process(head)
-
- if adjust_tail then
- adjust_tail.next = nil -- todo
- end
- if pre_adjust_tail then
- pre_adjust_tail.next = nil -- todo
- end
- if method == "additional" then
- width = width + natural
- end
+ end
- setwhd(hlist,width,height,depth)
+ process(head)
- local delta = width - natural
- if delta == 0 then
- setfield(hlist,"glue_sign",0)
- setfield(hlist,"glue_order",0)
- setfield(hlist,"glue_set",0)
- elseif delta > 0 then
- -- natural width smaller than requested width
- local order = (total_stretch[4] ~= 0 and 4 or total_stretch[3] ~= 0 and 3) or
- (total_stretch[2] ~= 0 and 2 or total_stretch[1] ~= 0 and 1) or 0
- if cal_expand_ratio and order == 0 and font_stretch > 0 then -- check sign of font_stretch
- font_expand_ratio = delta/font_stretch
+ if adjust_tail then
+ adjust_tail.next = nil -- todo
+ end
+ if pre_adjust_tail then
+ pre_adjust_tail.next = nil -- todo
+ end
+ if method == "additional" then
+ width = width + natural
+ end
- if font_expand_ratio > 1 then
- font_expand_ratio = 1
- end
+ setwhd(hlist,width,height,depth)
- local fontexps, lastfont
- for i=1,expansion_index do
- local g = expansion_stack[i]
- local e = 0
- local char = isglyph(g)
- if char then
- local currentfont = getfont(g)
- if currentfont ~= lastfont then
- fontexps = expansions[currentfont]
- lastfont = currentfont
- end
- local data = fontexps[char]
- if trace_expansion then
- setnodecolor(g,"hz:positive")
- end
- e = font_expand_ratio * data.glyphstretch / 1000
- else
- local kern = getfield(g,"kern")
- local stretch, shrink = kern_stretch_shrink(g,kern)
- e = font_expand_ratio * stretch / 1000
- end
- setfield(g,"expansion_factor",e)
- end
- end
- local tso = total_stretch[order]
- if tso ~= 0 then
- setfield(hlist,"glue_sign",1)
- setfield(hlist,"glue_order",order)
- setfield(hlist,"glue_set",delta/tso)
- else
+ local delta = width - natural
+ if delta == 0 then
setfield(hlist,"glue_sign",0)
- setfield(hlist,"glue_order",order)
+ setfield(hlist,"glue_order",0)
setfield(hlist,"glue_set",0)
- end
- if font_expand_ratio ~= 0 then
- -- todo
- elseif order == 0 then -- and getlist(hlist) then
- last_badness = calculate_badness(delta,total_stretch[0])
- if last_badness > tex.hbadness then
- if last_badness > 100 then
- diagnostics.underfull_hbox(hlist,line,last_badness)
- else
- diagnostics.loose_hbox(hlist,line,last_badness)
+ elseif delta > 0 then
+ -- natural width smaller than requested width
+ local order = (total_stretch[4] ~= 0 and 4 or total_stretch[3] ~= 0 and 3) or
+ (total_stretch[2] ~= 0 and 2 or total_stretch[1] ~= 0 and 1) or 0
+ if cal_expand_ratio and order == 0 and font_stretch > 0 then -- check sign of font_stretch
+ font_expand_ratio = delta/font_stretch
+
+ if font_expand_ratio > 1 then
+ font_expand_ratio = 1
+ end
+
+ local fontexps, lastfont
+ for i=1,expansion_index do
+ local g = expansion_stack[i]
+ local e = 0
+ local char = isglyph(g)
+ if char then
+ local currentfont = getfont(g)
+ if currentfont ~= lastfont then
+ fontexps = expansions[currentfont]
+ lastfont = currentfont
+ end
+ local data = fontexps[char]
+ if trace_expansion then
+ setnodecolor(g,"hz:positive")
+ end
+ e = font_expand_ratio * data.glyphstretch / 1000
+ else
+ local kern = getkern(g)
+ local stretch, shrink = kern_stretch_shrink(g,kern)
+ e = font_expand_ratio * stretch / 1000
+ end
+ setfield(g,"expansion_factor",e)
end
end
- end
- else
- -- natural width larger than requested width
- local order = total_shrink[4] ~= 0 and 4 or total_shrink[3] ~= 0 and 3
- or total_shrink[2] ~= 0 and 2 or total_shrink[1] ~= 0 and 1 or 0
- if cal_expand_ratio and order == 0 and font_shrink > 0 then -- check sign of font_shrink
- font_expand_ratio = delta/font_shrink
-
- if font_expand_ratio < 1 then
- font_expand_ratio = -1
+ local tso = total_stretch[order]
+ if tso ~= 0 then
+ setfield(hlist,"glue_sign",1)
+ setfield(hlist,"glue_order",order)
+ setfield(hlist,"glue_set",delta/tso)
+ else
+ setfield(hlist,"glue_sign",0)
+ setfield(hlist,"glue_order",order)
+ setfield(hlist,"glue_set",0)
end
-
- local fontexps, lastfont
- for i=1,expansion_index do
- local g = expansion_stack[i]
- local e = 0
- local char = isglyph(g)
- if char then
- local currentfont = getfont(g)
- if currentfont ~= lastfont then
- fontexps = expansions[currentfont]
- lastfont = currentfont
- end
- local data = fontexps[char]
- if trace_expansion then
- setnodecolor(g,"hz:negative")
+ if font_expand_ratio ~= 0 then
+ -- todo
+ elseif order == 0 then -- and getlist(hlist) then
+ last_badness = calculate_badness(delta,total_stretch[0])
+ if last_badness > tex.hbadness then
+ if last_badness > 100 then
+ diagnostics.underfull_hbox(hlist,line,last_badness)
+ else
+ diagnostics.loose_hbox(hlist,line,last_badness)
end
- e = font_expand_ratio * data.glyphshrink / 1000
- else
- local kern = getfield(g,"kern")
- local stretch, shrink = kern_stretch_shrink(g,kern)
- e = font_expand_ratio * shrink / 1000
end
- setfield(g,"expansion_factor",e)
end
- end
- local tso = total_shrink[order]
- if tso ~= 0 then
- setfield(hlist,"glue_sign",2)
- setfield(hlist,"glue_order",order)
- setfield(hlist,"glue_set",-delta/tso)
else
- setfield(hlist,"glue_sign",0)
- setfield(hlist,"glue_order",order)
- setfield(hlist,"glue_set",0)
- end
- if font_expand_ratio ~= 0 then
- -- todo
- elseif tso < -delta and order == 0 then -- and getlist(hlist) then
- last_badness = 1000000
- setfield(hlist,"glue_set",1)
- local fuzz = - delta - total_shrink[0]
- local hfuzz = tex.hfuzz
- if fuzz > hfuzz or tex.hbadness < 100 then
- local overfullrule = tex.overfullrule
- if fuzz > hfuzz and overfullrule > 0 then
- -- weird, is always called and no rules shows up
- setfield(slide_node_list(list),"next",new_rule(overfullrule,nil,nil,getfield(hlist,"dir"))) -- todo: find_tail
+ -- natural width larger than requested width
+ local order = total_shrink[4] ~= 0 and 4 or total_shrink[3] ~= 0 and 3
+ or total_shrink[2] ~= 0 and 2 or total_shrink[1] ~= 0 and 1 or 0
+ if cal_expand_ratio and order == 0 and font_shrink > 0 then -- check sign of font_shrink
+ font_expand_ratio = delta/font_shrink
+
+ if font_expand_ratio < 1 then
+ font_expand_ratio = -1
+ end
+
+ local fontexps, lastfont
+ for i=1,expansion_index do
+ local g = expansion_stack[i]
+ local e = 0
+ local char = isglyph(g)
+ if char then
+ local currentfont = getfont(g)
+ if currentfont ~= lastfont then
+ fontexps = expansions[currentfont]
+ lastfont = currentfont
+ end
+ local data = fontexps[char]
+ if trace_expansion then
+ setnodecolor(g,"hz:negative")
+ end
+ e = font_expand_ratio * data.glyphshrink / 1000
+ else
+ local kern = getkern(g)
+ local stretch, shrink = kern_stretch_shrink(g,kern)
+ e = font_expand_ratio * shrink / 1000
+ end
+ setfield(g,"expansion_factor",e)
end
- diagnostics.overfull_hbox(hlist,line,-delta)
end
- elseif order == 0 and getlist(hlist) and last_badness > tex.hbadness then
- diagnostics.bad_hbox(hlist,line,last_badness)
+ local tso = total_shrink[order]
+ if tso ~= 0 then
+ setfield(hlist,"glue_sign",2)
+ setfield(hlist,"glue_order",order)
+ setfield(hlist,"glue_set",-delta/tso)
+ else
+ setfield(hlist,"glue_sign",0)
+ setfield(hlist,"glue_order",order)
+ setfield(hlist,"glue_set",0)
+ end
+ if font_expand_ratio ~= 0 then
+ -- todo
+ elseif tso < -delta and order == 0 then -- and getlist(hlist) then
+ last_badness = 1000000
+ setfield(hlist,"glue_set",1)
+ local fuzz = - delta - total_shrink[0]
+ local hfuzz = tex.hfuzz
+ if fuzz > hfuzz or tex.hbadness < 100 then
+ local overfullrule = tex.overfullrule
+ if fuzz > hfuzz and overfullrule > 0 then
+ -- weird, is always called and no rules shows up
+ setnext(slide_node_list(list),new_rule(overfullrule,nil,nil,getdir(hlist))) -- todo: find_tail
+ end
+ diagnostics.overfull_hbox(hlist,line,-delta)
+ end
+ elseif order == 0 and getlist(hlist) and last_badness > tex.hbadness then
+ diagnostics.bad_hbox(hlist,line,last_badness)
+ end
end
+ return hlist, last_badness
end
- return hlist, last_badness
-end
-xpack_nodes = hpack -- comment this for old fashioned expansion (we need to fix float mess)
+ xpack_nodes = hpack -- comment this for old fashioned expansion (we need to fix float mess)
-constructors.methods.hpack = hpack
-
-local function common_message(hlist,line,str)
- write_nl("")
- if status.output_active then -- unset
- write(str," has occurred while \\output is active")
- else
- write(str)
- end
- local fileline = status.linenumber
- if line > 0 then
- write(formatters[" in paragraph at lines %s--%s"](fileline,"--",fileline+line-1))
- elseif line < 0 then
- write(formatters[" in alignment at lines "](fileline,"--",fileline-line-1))
- else
- write(formatters[" detected at line %s"](fileline))
- end
- write_nl("")
- diagnostics.short_display(getlist(hlist),false)
- write_nl("")
- -- diagnostics.start()
- -- show_box(getlist(hlist))
- -- diagnostics.stop()
-end
-
-function diagnostics.overfull_hbox(hlist,line,d)
- common_message(hlist,line,formatters["Overfull \\hbox (%spt too wide)"](number.toscaled(d)))
-end
-
-function diagnostics.bad_hbox(hlist,line,b)
- common_message(hlist,line,formatters["Tight \\hbox (badness %i)"](b))
-end
-
-function diagnostics.underfull_hbox(hlist,line,b)
- common_message(hlist,line,formatters["Underfull \\hbox (badness %i)"](b))
-end
+ constructors.methods.hpack = hpack
-function diagnostics.loose_hbox(hlist,line,b)
- common_message(hlist,line,formatters["Loose \\hbox (badness %i)"](b))
end
diff --git a/tex/context/base/mkiv/node-met.lua b/tex/context/base/mkiv/node-met.lua
index ea6ce6aca..acdb1286e 100644
--- a/tex/context/base/mkiv/node-met.lua
+++ b/tex/context/base/mkiv/node-met.lua
@@ -63,12 +63,7 @@ end
nodes = nodes or { }
local nodes = nodes
------ gonuts = type(node.direct) == "table"
------.gonuts = gonuts
-
local nodecodes = nodes.nodecodes
-local hlist_code = nodecodes.hlist
-local vlist_code = nodecodes.vlist
nodes.tostring = node.tostring or tostring
nodes.copy = node.copy
@@ -107,8 +102,12 @@ nodes.protrusion_skippable = node.protrusion_skippable
nodes.check_discretionaries = node.check_discretionaries
nodes.write = node.write
+nodes.count = node.count
+nodes.length = node.length
+
nodes.has_attribute = node.has_attribute
nodes.set_attribute = node.set_attribute
+nodes.find_attribute = node.find_attribute
nodes.unset_attribute = node.unset_attribute
nodes.protect_glyphs = node.protect_glyphs
@@ -118,34 +117,6 @@ nodes.kerning = node.kerning
nodes.ligaturing = node.ligaturing
nodes.mlist_to_hlist = node.mlist_to_hlist
-if LUATEXVERSION < 0.97 then
-
- local getglue = node.getglue
-
- function node.is_zero_glue(n)
- local width, stretch, shrink = getglue(n)
- return width == 0 and stretch == 0 and shrink == 0
- end
-
-end
-
-if not node.rangedimensions then -- LUATEXVERSION < 0.99
-
- local dimensions = node.dimensions
- local getfield = node.getfield
- local find_tail = node.tail
-
- function node.rangedimensions(parent,first,last)
- return dimensions(
- getfield(parent,"glue_set"), getfield(parent,"glue_sign"), getfield(parent,"glue_order"),
- first, last or find_tail(first), getfield(parent,"dir")
- )
- end
-
- nodes.rangedimensions = node.rangedimensions
-
-end
-
if not node.getwhd then
local getfield = node.getfield
function node.getwhd(n)
@@ -196,69 +167,82 @@ local n_getfield = node.getfield
local n_setattr = node.setattr
local n_getattr = node.getattr
local n_getdisc = node.getdisc
-local n_getwhd = node.getwhd
local n_getleader = node.getleader
-local n_setnext = node.setnext or
+local n_setnext = node.setnext or -- always
function(c,next)
setfield(c,"next",n)
end
-local n_setprev = node.setprev or
+local n_setprev = node.setprev or -- always
function(c,prev)
setfield(c,"prev",p)
end
-local n_setlink = node.setlink or
- function(c1,c2)
- if c1 then setfield(c1,"next",c2) end
- if c2 then setfield(c2,"prev",c1) end
+local n_setlink = node.setlink or -- always
+-- function(c1,c2)
+-- if c1 then setfield(c1,"next",c2) end
+-- if c2 then setfield(c2,"prev",c1) end
+-- end
+ 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
+ setfield(h,"next",n)
+ setfield(n,"prev",h)
+ else
+ h = n
+ end
+ end
+ return h
end
-local n_setboth = node.setboth or
+local n_setboth = node.setboth or -- always
function(c,p,n)
setfield(c,"prev",p)
setfield(c,"next",n)
end
-node.setnext = n_setnext
-node.setprev = n_setprev
-node.setlink = n_setlink
-node.setboth = n_setboth
-
-nodes.getfield = n_getfield
-nodes.setfield = n_setfield
-nodes.getattr = n_getattr
-nodes.setattr = n_setattr
-
-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
------.getpre = node.getpre or function(n) local h, _, _, t = n_getdisc(n,true) return h, t end
------.getpost = node.getpost or function(n) local _, h, _, _, t = n_getdisc(n,true) return h, t end
------.getreplace = node.getreplace or function(n) local _, _, h, _, _, t = n_getdisc(n,true) return h, t end
-
-nodes.is_char = node.is_char
-nodes.ischar = node.is_char
-
-nodes.is_glyph = node.is_glyph
-nodes.isglyph = node.is_glyph
-
-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
-local n_copy_list = nodes.copy_list
-local n_find_tail = nodes.tail
-local n_insert_after = nodes.insert_after
-local n_insert_before = nodes.insert_before
-local n_slide = nodes.slide
-
-local n_remove_node = node.remove -- not yet nodes.remove
+node.setnext = n_setnext
+node.setprev = n_setprev
+node.setlink = n_setlink
+node.setboth = n_setboth
+
+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
+
+nodes.is_char = node.is_char
+nodes.ischar = node.is_char
+
+nodes.is_glyph = node.is_glyph
+nodes.isglyph = node.is_glyph
+
+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
+local n_copy_list = nodes.copy_list
+local n_find_tail = nodes.tail
+local n_insert_after = nodes.insert_after
+local n_insert_before = nodes.insert_before
+local n_slide = nodes.slide
+
+local n_remove_node = node.remove -- not yet nodes.remove
local function remove(head,current,free_too)
local t = current
@@ -311,26 +295,7 @@ function nodes.replace(head,current,new) -- no head returned if false
end
end
-local function count(stack,flat)
- local n = 0
- while stack do
- local id = n_getid(stack)
- if not flat and id == hlist_code or id == vlist_code then
- local list = n_getlist(stack)
- if list then
- n = n + 1 + count(list) -- self counts too
- else
- n = n + 1
- end
- else
- n = n + 1
- end
- stack = n_getnext(stack)
- end
- return n
-end
-
-nodes.count = count
+-- nodes.countall : see node-nut.lua
function nodes.append(head,current,...)
for i=1,select("#",...) do
@@ -662,7 +627,7 @@ local messyhack = table.tohash { -- temporary solution
}
table.setmetatableindex(keys,function(t,k)
- v = (k == "attributelist" or k == nodecodes.attributelist) and { } or getfields(k)
+ local v = (k == "attributelist" or k == nodecodes.attributelist) and { } or getfields(k)
if messyhack[k] then
for i=1,#v do
if v[i] == "subtype" then
diff --git a/tex/context/base/mkiv/node-mig.lua b/tex/context/base/mkiv/node-mig.lua
index 24bebb0cc..b3820a7d8 100644
--- a/tex/context/base/mkiv/node-mig.lua
+++ b/tex/context/base/mkiv/node-mig.lua
@@ -16,7 +16,7 @@ local report_nodes = logs.reporter("nodes","migrations")
local attributes = attributes
local nodes = nodes
-local tasks = nodes.tasks
+local enableaction = nodes.tasks.enableaction
local nuts = nodes.nuts
local tonut = nuts.tonut
@@ -26,7 +26,6 @@ local getid = nuts.getid
local getlist = nuts.getlist
local getattr = nuts.getattr
-local setfield = nuts.setfield
local setattr = nuts.setattr
local setlink = nuts.setlink
local setlist = nuts.setlist
@@ -139,21 +138,21 @@ end
experiments.register("marks.migrate", function(v)
if v then
- tasks.enableaction("mvlbuilders", "nodes.handlers.migrate")
+ enableaction("mvlbuilders", "nodes.handlers.migrate")
end
migrate_marks = v
end)
experiments.register("inserts.migrate", function(v)
if v then
- tasks.enableaction("mvlbuilders", "nodes.handlers.migrate")
+ enableaction("mvlbuilders", "nodes.handlers.migrate")
end
migrate_inserts = v
end)
experiments.register("inserts.migrate.nested", function(v)
if v then
- tasks.enableaction("mvlbuilders", "nodes.handlers.migrate")
+ enableaction("mvlbuilders", "nodes.handlers.migrate")
end
inserts_too = v
end)
diff --git a/tex/context/base/mkiv/node-nut.lua b/tex/context/base/mkiv/node-nut.lua
index cec272bcf..0c6714667 100644
--- a/tex/context/base/mkiv/node-nut.lua
+++ b/tex/context/base/mkiv/node-nut.lua
@@ -133,19 +133,90 @@ if not direct.setwhd then
end
end
-nuts.getwhd = direct.getwhd
-nuts.setwhd = direct.setwhd
-
-nuts.getfield = direct.getfield
-nuts.getnext = direct.getnext
-nuts.getprev = direct.getprev
-nuts.getid = direct.getid
-nuts.getattr = direct.get_attribute or direct.has_attribute or direct.getfield
-nuts.getchar = direct.getchar
-nuts.getfont = direct.getfont
-nuts.getsubtype = direct.getsubtype
-nuts.getlist = direct.getlist -- only hlist and vlist !
-nuts.getleader = direct.getleader
+if not direct.getcomponents then
+
+ local getfield = direct.getfield
+ local setfield = direct.setfield
+ local setsubtype = direct.setsubtype
+
+ local attributelist_code = nodecodes.attributelist
+
+ function direct.getcomponents(n) return getfield(n,"components") end
+ function direct.setcomponents(n,c) setfield(n,"components",c) end
+ function direct.getkern(n) return getfield(n,"kern") end
+ function direct.getwidth(n) return getfield(n,"width") end
+ function direct.setwidth(n,w) return setfield(n,"width",w) end
+ function direct.getheight(n) return getfield(n,"height") end
+ function direct.setheight(n,h) return setfield(n,"height",h) end
+ function direct.getdepth(n) return getfield(n,"depth") end
+ function direct.setdepth(n,d) return setfield(n,"depth",d) end
+ function direct.getshift(n) return getfield(n,"shift") end
+ function direct.setshift(n,s) return setfield(n,"shift",s) end
+ function direct.getpenalty(n) return getfield(n,"penalty") end
+ function direct.setpenalty(n,p) setfield(n,"penalty",p) end
+ function direct.getdir(n) return getfield(n,"dir") end
+ function direct.setdir(n,p) setfield(n,"dir",p) end
+ function direct.getlanguage(n) return getfield(n,"lang") end
+ function direct.setlanguage(n,l) return setfield(n,"lang",l) end
+ function direct.getattributelist(n) getfield(n,"attr") end
+
+ function direct.getnucleus(n) return getfield(n,"nucleus") end
+ function direct.setnucleus(n,p) return setfield(n,"nucleus",p) end
+ function direct.getsup(n) return getfield(n,"sup") end
+ function direct.setsup(n,p) return setfield(n,"sup",p) end
+ function direct.getsub(n) return getfield(n,"sub") end
+ function direct.setsub(n,p) return setfield(n,"sub",p) end
+
+ function direct.setattributelist(n,a)
+ if a and type(a) ~= attributelist_code then
+ a = getfield(a,"attr")
+ end
+ setfield(n,"attr",a)
+ end
+
+ function direct.setkern(n,k,s)
+ setfield(n,"kern",k)
+ if s then
+ setsubtype(n,s)
+ end
+ end
+
+ function direct.setfont(n,f,c)
+ setfield(n,"font",f)
+ if c then
+ setfield(n,"char",f)
+ end
+ end
+
+ function direct.getoffsets(n)
+ return getfield(n,"xoffset"), getfield(n,"yoffset")
+ end
+
+ function direct.setoffsets(n,x,y)
+ if x then
+ setfield(n,"xoffset",x)
+ end
+ if y then
+ setfield(n,"yoffset",y)
+ end
+ end
+
+end
+
+-- if LUATEXVERSION < 1.004 then
+-- local gc = direct.getcomponents
+-- getcomponents = function(n) local c = gc(n) return c ~= 0 and c or nil end
+-- end
+
+-- local hash = table.setmetatableindex("number")
+-- local ga = direct.get_attribute
+-- function direct.get_attribute(n,a)
+-- hash[a] = hash[a] + 1
+-- return ga(n,a)
+-- end
+-- function nuts.reportattr()
+-- inspect(hash)
+-- end
-- local function track(name)
-- local n = 0
@@ -163,12 +234,6 @@ nuts.getleader = direct.getleader
-- setters
-nuts.setfield = direct.setfield
-nuts.setattr = direct.set_attribute or setfield
-
-nuts.getbox = direct.getbox
-nuts.setbox = direct.setbox
-
-- helpers
nuts.tostring = direct.tostring
@@ -199,6 +264,10 @@ nuts.is_direct = direct.is_direct
nuts.is_nut = direct.is_direct
nuts.first_glyph = direct.first_glyph
nuts.has_glyph = direct.has_glyph or direct.first_glyph
+nuts.count = direct.count
+nuts.length = direct.length
+nuts.find_attribute = direct.find_attribute
+nuts.unset_attribute = direct.unset_attribute
nuts.current_attr = direct.current_attr
nuts.has_field = direct.has_field
@@ -228,56 +297,95 @@ if not direct.mlist_to_hlist then -- needed
end
-if LUATEXVERSION < 0.97 then
-
- local getglue = direct.getglue
-
- function direct.is_zero_glue(n)
- local width, stretch, shrink = getglue(n)
- return width == 0 and stretch == 0 and shrink == 0
- end
-
-end
-
-if not direct.rangedimensions then -- LUATEXVERSION < 0.99
-
- local dimensions = direct.dimensions
- local getfield = direct.getfield
- local find_tail = direct.tail
+nuts.getfield = direct.getfield
+nuts.setfield = direct.setfield
- function direct.rangedimensions(parent,first,last)
- return dimensions(
- getfield(parent,"glue_set"), getfield(parent,"glue_sign"), getfield(parent,"glue_order"),
- first, last or find_tail(first), getfield(parent,"dir")
- )
- end
+nuts.getnext = direct.getnext
+nuts.setnext = direct.setnext
- nuts.rangedimensions = direct.rangedimensions
+nuts.getid = direct.getid
-end
+nuts.getprev = direct.getprev
+nuts.setprev = direct.setprev
-local getglue = direct.getglue
-local setglue = direct.setglue
-local is_zero_glue = direct.is_zero_glue
+nuts.getattr = direct.get_attribute
+nuts.setattr = direct.set_attribute
+nuts.takeattr = direct.unset_attribute -- ?
+nuts.is_zero_glue = direct.is_zero_glue
nuts.effective_glue = direct.effective_glue
-nuts.getglue = getglue
-nuts.setglue = setglue
-nuts.is_zero_glue = is_zero_glue
+
+nuts.getglue = direct.getglue
+nuts.setglue = direct.setglue
nuts.getdisc = direct.getdisc
-nuts.getwhd = direct.getwhd
nuts.setdisc = direct.setdisc
+nuts.getdiscretionary = direct.getdisc
+nuts.setdiscretionary = direct.setdisc
+
+nuts.getwhd = direct.getwhd
+nuts.setwhd = direct.setwhd
+nuts.getwidth = direct.getwidth
+nuts.setwidth = direct.setwidth
+nuts.getheight = direct.getheight
+nuts.setheight = direct.setheight
+nuts.getdepth = direct.getdepth
+nuts.setdepth = direct.setdepth
+nuts.getshift = direct.getshift
+nuts.setshift = direct.setshift
+
+nuts.getnucleus = direct.getnucleus
+nuts.setnucleus = direct.setnucleus
+nuts.getsup = direct.getsup
+nuts.setsup = direct.setsup
+nuts.getsub = direct.getsub
+nuts.setsub = direct.setsub
+
+nuts.getchar = direct.getchar
nuts.setchar = direct.setchar
-nuts.setnext = direct.setnext
-nuts.setprev = direct.setprev
-nuts.setboth = direct.setboth
+nuts.getfont = direct.getfont
+nuts.setfont = direct.setfont
+
nuts.getboth = direct.getboth
+nuts.setboth = direct.setboth
nuts.setlink = direct.setlink
+nuts.setsplit = direct.setsplit
+
+nuts.getlist = direct.getlist -- only hlist and vlist !
nuts.setlist = direct.setlist
+nuts.getleader = direct.getleader
nuts.setleader = direct.setleader
+nuts.getcomponents = direct.getcomponents
+nuts.setcomponents = direct.setcomponents
+
+nuts.getsubtype = direct.getsubtype
nuts.setsubtype = direct.setsubtype
+nuts.getlang = direct.getlang
+nuts.setlang = direct.setlang
+nuts.getlanguage = direct.getlang
+nuts.setlanguage = direct.setlang
+
+nuts.getattrlist = direct.getattributelist
+nuts.setattrlist = direct.setattributelist
+nuts.getattributelist = direct.getattributelist
+nuts.setattributelist = direct.setattributelist
+
+nuts.getoffsets = direct.getoffsets
+nuts.setoffsets = direct.setoffsets
+
+nuts.getkern = direct.getkern
+nuts.setkern = direct.setkern
+
+nuts.getdir = direct.getdir
+nuts.setdir = direct.setdir
+
+nuts.getpenalty = direct.getpenalty
+nuts.setpenalty = direct.setpenalty
+
+nuts.getbox = direct.getbox
+nuts.setbox = direct.setbox
+
nuts.is_char = direct.is_char
nuts.ischar = direct.is_char
nuts.is_glyph = direct.is_glyph
@@ -313,6 +421,11 @@ local function remove(head,current,free_too)
return head, current, t
end
+-- alias
+
+nuts.getsurround = nuts.getkern
+nuts.setsurround = nuts.setkern
+
-- bad: we can have prev's being glue_spec
nuts.remove = remove
@@ -326,11 +439,14 @@ function nuts.replace(head,current,new) -- no head returned if false
head, current, new = false, head, current
end
local prev, next = d_getboth(current)
- if next then
- d_setlink(new,next)
- end
- if prev then
- d_setlink(prev,new)
+-- if next then
+-- d_setlink(new,next)
+-- end
+-- if prev then
+-- d_setlink(prev,new)
+-- end
+ if prev or next then
+ d_setlink(prev,new,next)
end
if head then
if head == current then
@@ -344,14 +460,14 @@ function nuts.replace(head,current,new) -- no head returned if false
end
end
-local function count(stack,flat)
+local function countall(stack,flat)
local n = 0
while stack do
local id = d_getid(stack)
if not flat and id == hlist_code or id == vlist_code then
local list = d_getlist(stack)
if list then
- n = n + 1 + count(list) -- self counts too
+ n = n + 1 + countall(list) -- self counts too
else
n = n + 1
end
@@ -363,7 +479,11 @@ local function count(stack,flat)
return n
end
-nuts.count = count
+nuts.countall = countall
+
+function nodes.countall(stack,flat)
+ return countall(tonut(stack),flat)
+end
function nuts.append(head,current,...)
for i=1,select("#",...) do
@@ -379,7 +499,7 @@ function nuts.prepend(head,current,...)
return head, current
end
-function nuts.linked(...)
+function nuts.linked(...) -- slides !
local head, last
for i=1,select("#",...) do
local next = select(i,...)
diff --git a/tex/context/base/mkiv/node-ppt.lua b/tex/context/base/mkiv/node-ppt.lua
index 82acf2ff4..5ebfca87d 100644
--- a/tex/context/base/mkiv/node-ppt.lua
+++ b/tex/context/base/mkiv/node-ppt.lua
@@ -27,7 +27,6 @@ local getnext = nuts.getnext
local getprev = nuts.getprev
local getsubtype = nuts.getsubtype
local getfield = nuts.getfield
-local setfield = nuts.setfield
local getlist = nuts.getlist
local setlist = nuts.setlist
local removenode = nuts.remove
@@ -102,8 +101,7 @@ local actions = { } properties.actions = actions
table.setmetatableindex(actions,function(t,k)
report("unknown property action %a",k)
- local v = function() end
- return v
+ return function() end
end)
local f_delayed = formatters["return function(target,head,where,propdata,parent) %s end"]
@@ -314,7 +312,7 @@ local anchored = {
}
table.setmetatableindex(anchored,function(t,k)
- v = anchored[v_after]
+ local v = anchored[v_after]
t[k] = v
return v
end)
diff --git a/tex/context/base/mkiv/node-pro.lua b/tex/context/base/mkiv/node-pro.lua
index 713d78f07..8a501a590 100644
--- a/tex/context/base/mkiv/node-pro.lua
+++ b/tex/context/base/mkiv/node-pro.lua
@@ -6,23 +6,17 @@ if not modules then modules = { } end modules ['node-pro'] = {
license = "see context related readme files"
}
-local utfchar = utf.char
-local format, concat = string.format, table.concat
-
local trace_callbacks = false trackers .register("nodes.callbacks", function(v) trace_callbacks = v end)
local force_processors = false directives.register("nodes.processors.force", function(v) force_processors = v end)
local report_nodes = logs.reporter("nodes","processors")
-local nodes = nodes
-local tasks = nodes.tasks
-local nuts = nodes.nuts
-
-local first_glyph = nodes.first_glyph
-local has_glyph = nodes.has_glyph
+local nodes = nodes
+local tasks = nodes.tasks
+local nuts = nodes.nuts
-nodes.processors = nodes.processors or { }
-local processors = nodes.processors
+nodes.processors = nodes.processors or { }
+local processors = nodes.processors
-- vbox: grouptype: vbox vtop output split_off split_keep | box_type: exactly|aditional
-- hbox: grouptype: hbox adjusted_hbox(=hbox_in_vmode) | box_type: exactly|aditional
@@ -35,6 +29,9 @@ do
local isglyph = nuts.isglyph
local getnext = nuts.getnext
+ local utfchar = utf.char
+ local concat = table.concat
+
local n = 0
local function reconstruct(head) -- we probably have a better one
@@ -72,125 +69,164 @@ local tracer = processors.tracer
processors.enabled = true -- this will become a proper state (like trackers)
-function processors.pre_linebreak_filter(head,groupcode) -- ,size,packtype,direction
- -- local first, found = first_glyph(head) -- they really need to be glyphs
- local found = force_processors or has_glyph(head)
- if found then
- if trace_callbacks then
- local before = nodes.count(head,true)
- local head, done = actions(head,groupcode) -- ,size,packtype,direction
- local after = nodes.count(head,true)
- if done then
- tracer("pre_linebreak","changed",head,groupcode,before,after,true)
+do
+
+ local has_glyph = nodes.has_glyph
+
+ function processors.pre_linebreak_filter(head,groupcode) -- ,size,packtype,direction
+ local found = force_processors or has_glyph(head)
+ if found then
+ if trace_callbacks then
+ local before = nodes.count(head,true)
+ local head, done = actions(head,groupcode) -- ,size,packtype,direction
+ local after = nodes.count(head,true)
+ if done then
+ tracer("pre_linebreak","changed",head,groupcode,before,after,true)
+ else
+ tracer("pre_linebreak","unchanged",head,groupcode,before,after,true)
+ end
+ return done and head or true
else
- tracer("pre_linebreak","unchanged",head,groupcode,before,after,true)
+ local head, done = actions(head,groupcode) -- ,size,packtype,direction
+ return done and head or true
end
- return done and head or true
- else
- local head, done = actions(head,groupcode) -- ,size,packtype,direction
- return done and head or true
+ elseif trace_callbacks then
+ local n = nodes.count(head,false)
+ tracer("pre_linebreak","no chars",head,groupcode,n,n)
end
- elseif trace_callbacks then
- local n = nodes.count(head,false)
- tracer("pre_linebreak","no chars",head,groupcode,n,n)
+ return true
end
- return true
-end
-local function hpack_filter(head,groupcode,size,packtype,direction,attributes)
- -- local first, found = first_glyph(head) -- they really need to be glyphs
- local found = force_processors or has_glyph(head)
- if found then
- if trace_callbacks then
- local before = nodes.count(head,true)
- local head, done = actions(head,groupcode,size,packtype,direction,attributes)
- local after = nodes.count(head,true)
- if done then
- tracer("hpack","changed",head,groupcode,before,after,true)
+ local function hpack_filter(head,groupcode,size,packtype,direction,attributes)
+ local found = force_processors or has_glyph(head)
+ if found then
+ if trace_callbacks then
+ local before = nodes.count(head,true)
+ local head, done = actions(head,groupcode,size,packtype,direction,attributes)
+ local after = nodes.count(head,true)
+ if done then
+ tracer("hpack","changed",head,groupcode,before,after,true)
+ else
+ tracer("hpack","unchanged",head,groupcode,before,after,true)
+ end
+ return done and head or true
else
- tracer("hpack","unchanged",head,groupcode,before,after,true)
+ local head, done = actions(head,groupcode,size,packtype,direction,attributes)
+ return done and head or true
end
- return done and head or true
- else
- local head, done = actions(head,groupcode,size,packtype,direction,attributes)
- return done and head or true
+ elseif trace_callbacks then
+ local n = nodes.count(head,false)
+ tracer("hpack","no chars",head,groupcode,n,n)
end
- elseif trace_callbacks then
- local n = nodes.count(head,false)
- tracer("hpack","no chars",head,groupcode,n,n)
+ return true
end
- return true
-end
-processors.hpack_filter = hpack_filter
+ processors.hpack_filter = hpack_filter
-do
+ do
+
+ local setfield = nodes.setfield
+ local hpack = nodes.hpack
+
+ function nodes.fullhpack(head,...)
+ local ok = hpack_filter(head)
+ if not done or done == true then
+ ok = head
+ end
+ local hp, b = hpack(ok,...)
+ setfield(hp,"prev",nil)
+ setfield(hp,"next",nil)
+ return hp, b
+ end
+
+ end
+
+ do
- local setfield = nodes.setfield
- local hpack = nodes.hpack
+ local setboth = nuts.setboth
+ local hpack = nuts.hpack
- function nodes.fullhpack(head,...)
- local ok = hpack_filter(head)
- if not done or done == true then
- ok = head
+ function nuts.fullhpack(head,...)
+ local ok = hpack_filter(tonode(head))
+ if not done or done == true then
+ ok = head
+ else
+ ok = tonut(ok)
+ end
+ local hp, b = hpack(...)
+ setboth(hp)
+ return hp, b
end
- local hp, b = hpack(ok,...)
- setfield(hp,"prev",nil)
- setfield(hp,"next",nil)
- return hp, b
+
end
+ callbacks.register('pre_linebreak_filter', processors.pre_linebreak_filter, "all kind of horizontal manipulations (before par break)")
+ callbacks.register('hpack_filter' , processors.hpack_filter, "all kind of horizontal manipulations (before hbox creation)")
+
end
do
- local setboth = nuts.setboth
- local hpack = nuts.hpack
+ local actions = tasks.actions("finalizers") -- head, where
+
+ -- beware, these are packaged boxes so no first_glyph test
+ -- maybe some day a hash with valid groupcodes
+ --
+ -- beware, much can pass twice, for instance vadjust passes two times
+ --
+ -- something weird here .. group mvl when making a vbox
- function nuts.fullhpack(head,...)
- local ok = hpack_filter(tonode(head))
- if not done or done == true then
- ok = head
+ function processors.post_linebreak_filter(head,groupcode)
+ if trace_callbacks then
+ local before = nodes.count(head,true)
+ local head, done = actions(head,groupcode)
+ local after = nodes.count(head,true)
+ if done then
+ tracer("post_linebreak","changed",head,groupcode,before,after,true)
+ else
+ tracer("post_linebreak","unchanged",head,groupcode,before,after,true)
+ end
+ return done and head or true
else
- ok = tonut(ok)
+ local head, done = actions(head,groupcode)
+ return done and head or true
end
- local hp, b = hpack(...)
- setboth(hp)
- return hp, b
end
+ callbacks.register('post_linebreak_filter', processors.post_linebreak_filter,"all kind of horizontal manipulations (after par break)")
+
end
-callbacks.register('pre_linebreak_filter', processors.pre_linebreak_filter, "all kind of horizontal manipulations (before par break)")
-callbacks.register('hpack_filter' , processors.hpack_filter, "all kind of horizontal manipulations (before hbox creation)")
-
-local actions = tasks.actions("finalizers") -- head, where
-
--- beware, these are packaged boxes so no first_glyph test
--- maybe some day a hash with valid groupcodes
---
--- beware, much can pass twice, for instance vadjust passes two times
---
--- something weird here .. group mvl when making a vbox
-
-function processors.post_linebreak_filter(head,groupcode)
- if trace_callbacks then
- local before = nodes.count(head,true)
- local head, done = actions(head,groupcode)
- local after = nodes.count(head,true)
- if done then
- tracer("post_linebreak","changed",head,groupcode,before,after,true)
- else
- tracer("post_linebreak","unchanged",head,groupcode,before,after,true)
+do
+
+ local texnest = tex.nest
+
+ local getlist = nodes.getlist
+ local getsubtype = nodes.getsubtype
+ local setlist = nodes.setlist
+
+ local line_code = nodes.listcodes.line
+
+ local actions = tasks.actions("contributers")
+
+ function processors.contribute_filter(groupcode)
+ if groupcode == "box" then -- "pre_box"
+ local whatever = texnest[texnest.ptr]
+ if whatever then
+ local tail = whatever.tail
+ if tail and getsubtype(tail) == line_code then
+ local okay, done = actions(tail,groupcode)
+ if okay and okay ~= tail then
+ setlist(tail,okay)
+ end
+ end
+ end
end
- return done and head or true
- else
- local head, done = actions(head,groupcode)
- return done and head or true
end
-end
-callbacks.register('post_linebreak_filter', processors.post_linebreak_filter,"all kind of horizontal manipulations (after par break)")
+ callbacks.register('contribute_filter', processors.contribute_filter,"things done with lines")
+
+end
statistics.register("h-node processing time", function()
return statistics.elapsedseconds(nodes,"including kernel") -- hm, ok here?
diff --git a/tex/context/base/mkiv/node-ref.lua b/tex/context/base/mkiv/node-ref.lua
index c082ac817..b313a00b6 100644
--- a/tex/context/base/mkiv/node-ref.lua
+++ b/tex/context/base/mkiv/node-ref.lua
@@ -32,7 +32,7 @@ local cleanupdestinations = true
local transparencies = attributes.transparencies
local colors = attributes.colors
local references = structures.references
-local tasks = nodes.tasks
+local enableaction = nodes.tasks.enableaction
local trace_references = false trackers.register("nodes.references", function(v) trace_references = v end)
local trace_destinations = false trackers.register("nodes.destinations", function(v) trace_destinations = v end)
@@ -60,10 +60,15 @@ local getprev = nuts.getprev
local getid = nuts.getid
local getlist = nuts.getlist
local setlist = nuts.setlist
+local getwidth = nuts.getwidth
+local setwidth = nuts.setwidth
+local getheight = nuts.getheight
local getattr = nuts.getattr
local setattr = nuts.setattr
local getsubtype = nuts.getsubtype
local getwhd = nuts.getwhd
+local getdir = nuts.getdir
+local setshift = nuts.setshift
local hpack_list = nuts.hpack
local vpack_list = nuts.vpack
@@ -212,7 +217,7 @@ local function dimensions(parent,start,stop) -- in principle we could move some
report_area("dimensions taken of vlist")
end
local w, h, d = vlist_dimensions(first,last,parent)
- local ht = getfield(first,"height")
+ local ht = getheight(first)
return w, ht, d + h - ht, first
else
-- return hlist_dimensions(start,stop,parent)
@@ -286,8 +291,9 @@ if first == last and getid(parent) == vlist_code and getid(first) == hlist_code
setlink(result,getlist(first))
setlist(first,result)
else
- setlink(getprev(first),result)
- setlink(result,first)
+ -- setlink(getprev(first),result)
+ -- setlink(result,first)
+ setlink(getprev(first),result,first)
end
return head, last
end
@@ -345,8 +351,9 @@ local function inject_list(id,current,reference,make,stack,pardir,txtdir)
setlist(current,result)
elseif moveright then -- brr no prevs done
-- result after first
- setlink(result,getnext(first))
- setlink(first,result)
+ -- setlink(result,getnext(first))
+ -- setlink(first,result)
+ setlink(first,result,getnext(first))
else
-- first after result
setlink(result,first)
@@ -405,9 +412,9 @@ local function inject_areas(head,attribute,make,stack,done,skip,parent,pardir,tx
done[r] = done[r] - 1
end
elseif id == dir_code then
- txtdir = getfield(current,"dir")
+ txtdir = getdir(current)
elseif id == localpar_code then
- pardir = getfield(current,"dir")
+ pardir = getdir(current)
elseif id == glue_code and getsubtype(current) == leftskip_code then -- any glue at the left?
--
else
@@ -457,9 +464,9 @@ local function inject_area(head,attribute,make,stack,done,parent,pardir,txtdir)
end
end
elseif id == dir_code then
- txtdir = getfield(current,"dir")
+ txtdir = getdir(current)
elseif id == localpar_code then
- pardir = getfield(current,"dir")
+ pardir = getdir(current)
else
local r = getattr(current,attribute)
if r and not done[r] then
@@ -501,8 +508,8 @@ local function addstring(what,str,shift) --todo make a pluggable helper (in font
end
local text = typesetters.tohpack(str,infofont)
local rule = new_rule(emwidth/5,4*exheight,3*exheight)
- setfield(text,"shift",shift)
- return hpack_list(nuts.linked(text,rule))
+ setshift(text,shift)
+ return hpack_list(setlink(text,rule))
end
end
end
@@ -540,30 +547,30 @@ local function colorize(width,height,depth,n,reference,what,sr,offset)
setattr(rule,a_transparency,u_transparency)
if width < 0 then
local kern = new_kern(width)
- setfield(rule,"width",-width)
+ setwidth(rule,-width)
setnext(kern,rule)
setprev(rule,kern)
return kern
elseif sr and sr ~= "" then
local text = addstring(what,sr,shift)
if text then
- local kern = new_kern(-getfield(text,"width"))
- setlink(kern,text)
- setlink(text,rule)
+ local kern = new_kern(-getwidth(text))
+ -- setlink(kern,text)
+ -- setlink(text,rule)
+ setlink(kern,text,rule)
return kern
end
end
return rule
end
-local function justadd(what,sr,shift)
+local function justadd(what,sr,shift,current) -- needs testing
if sr and sr ~= "" then
local text = addstring(what,sr,shift)
if text then
- local kern = new_kern(-getfield(text,"width"))
- setlink(kern,text)
- setlink(text,rule)
- return kern
+ local kern = new_kern(-getwidth(text))
+ setlink(kern,text,current)
+ return new_hlist(kern)
end
end
end
@@ -637,17 +644,12 @@ local function makereference(width,height,depth,reference) -- height and depth a
end
if trace_references then
local step = 65536
--- result = hpack_list(colorize(width,height-step,depth-step,2,reference,"reference",texts,show_references)) -- step subtracted so that we can see seperate links
--- setfield(result,"width",0)
-result = new_hlist(colorize(width,height-step,depth-step,2,reference,"reference",texts,show_references)) -- step subtracted so that we can see seperate links
+ result = new_hlist(colorize(width,height-step,depth-step,2,reference,"reference",texts,show_references)) -- step subtracted so that we can see seperate links
current = result
elseif texts then
- texts = justadd("reference",texts,show_references)
+ texts = justadd("reference",texts,show_references,current)
if texts then
--- result = hpack_list(texts)
--- setfield(result,"width",0)
-result = new_hlist(texts)
- current = result
+ current = texts
end
end
if current then
@@ -656,11 +658,7 @@ result = new_hlist(texts)
result = annot
end
references.registerpage(n)
--- result = hpack_list(result,0)
--- setfield(result,"width",0)
--- setfield(result,"height",0)
--- setfield(result,"depth",0)
-result = new_hlist(result)
+ result = new_hlist(result)
if cleanupreferences then stack[reference] = nil end
return result, resolved
elseif trace_references then
@@ -757,9 +755,7 @@ local function makedestination(width,height,depth,reference)
step = 4*65536
width, height, depth = 5*step, 5*step, 0
end
--- local rule = hpack_list(colorize(width,height,depth,3,reference,"destination",texts,show_destinations))
--- setfield(rule,"width",0)
-local rule = new_list(colorize(width,height,depth,3,reference,"destination",texts,show_destinations))
+ local rule = new_hlist(colorize(width,height,depth,3,reference,"destination",texts,show_destinations))
if not result then
result, current = rule, rule
else
@@ -768,15 +764,9 @@ local rule = new_list(colorize(width,height,depth,3,reference,"destination",text
end
width, height = width - step, height - step
elseif texts then
- texts = justadd("destination",texts,show_destinations)
+ texts = justadd("destination",texts,show_destinations,current)
if texts then
--- result = hpack_list(texts)
--- if result then
--- setfield(result,"width",0)
--- current = result
--- end
-result = new_list(texts)
-current = result
+ current = texts
end
end
nofdestinations = nofdestinations + 1
@@ -791,12 +781,7 @@ current = result
current = find_node_tail(annot)
end
if result then
- -- some internal error
--- result = hpack_list(result,0)
--- setfield(result,"width",0)
--- setfield(result,"height",0)
--- setfield(result,"depth",0)
-result = new_hlist(result)
+ result = new_hlist(result)
end
if cleanupdestinations then stack[reference] = nil end
return result, resolved
@@ -932,8 +917,8 @@ statistics.register("interactive elements", function()
end)
function references.enableinteraction()
- tasks.enableaction("shipouts","nodes.references.handler")
- tasks.enableaction("shipouts","nodes.destinations.handler")
+ enableaction("shipouts","nodes.references.handler")
+ enableaction("shipouts","nodes.destinations.handler")
function references.enableinteraction() end
end
diff --git a/tex/context/base/mkiv/node-res.lua b/tex/context/base/mkiv/node-res.lua
index cb06ae488..8b7ec1a62 100644
--- a/tex/context/base/mkiv/node-res.lua
+++ b/tex/context/base/mkiv/node-res.lua
@@ -79,14 +79,18 @@ local setchar = nuts.setchar
local setlist = nuts.setlist
local setwhd = nuts.setwhd
local setglue = nuts.setglue
+local setdisc = nuts.setdisc
+local setfont = nuts.setfont
+local setkern = nuts.setkern
+local setpenalty = nuts.setpenalty
+local setdir = nuts.setdir
+local setshift = nuts.setshift
+local setwidth = nuts.setwidth
local copy_nut = nuts.copy
local new_nut = nuts.new
local flush_nut = nuts.flush
-local copy_node = nodes.copy
-local new_node = nodes.new
-
-- at some point we could have a dual set (the overhead of tonut is not much larger than
-- metatable associations at the lua/c end esp if we also take assignments into account
@@ -181,23 +185,26 @@ local wordboundary = register_nut(new_nut("boundary",boundarycodes.word))
-- the dir field needs to be set otherwise crash:
-local rule = register_nut(new_nut("rule")) setfield(rule, "dir","TLT")
-local emptyrule = register_nut(new_nut("rule",rulecodes.empty)) setfield(rule, "dir","TLT")
-local userrule = register_nut(new_nut("rule",rulecodes.user)) setfield(rule, "dir","TLT")
-local hlist = register_nut(new_nut("hlist")) setfield(hlist,"dir","TLT")
-local vlist = register_nut(new_nut("vlist")) setfield(vlist,"dir","TLT")
+local rule = register_nut(new_nut("rule")) setdir(rule, "TLT")
+local emptyrule = register_nut(new_nut("rule",rulecodes.empty)) setdir(rule, "TLT")
+local userrule = register_nut(new_nut("rule",rulecodes.user)) setdir(rule, "TLT")
+local hlist = register_nut(new_nut("hlist")) setdir(hlist,"TLT")
+local vlist = register_nut(new_nut("vlist")) setdir(vlist,"TLT")
function nutpool.glyph(fnt,chr)
local n = copy_nut(glyph)
- if fnt then setfield(n,"font",fnt) end
- if chr then setchar(n,chr) end
+ if fnt then
+ setfont(n,fnt,chr)
+ elseif chr then
+ setchar(n,chr)
+ end
return n
end
function nutpool.penalty(p)
local n = copy_nut(penalty)
if p and p ~= 0 then
- setfield(n,"penalty",p)
+ setpenalty(n,p)
end
return n
end
@@ -205,7 +212,7 @@ end
function nutpool.kern(k)
local n = copy_nut(kern)
if k and k ~= 0 then
- setfield(n,"kern",k)
+ setkern(n,k)
end
return n
end
@@ -228,39 +235,20 @@ end
function nutpool.fontkern(k)
local n = copy_nut(fontkern)
- setfield(n,"kern",k)
+ if k and k ~= 0 then
+ setkern(n,k)
+ end
return n
end
function nutpool.italickern(k)
local n = copy_nut(italickern)
if k and k ~= 0 then
- setfield(n,"kern",k)
+ setkern(n,k)
end
return n
end
--- function nutpool.gluespec(width,stretch,shrink,stretch_order,shrink_order)
--- -- maybe setglue
--- local s = copy_nut(glue_spec)
--- if width and width ~= 0 then
--- setfield(s,"width",width)
--- end
--- if stretch and stretch ~= 0 then
--- setfield(s,"stretch",stretch)
--- end
--- if shrink and shrink ~= 0 then
--- setfield(s,"shrink",shrink)
--- end
--- if stretch_order and stretch_order ~= 0 then
--- setfield(s,"stretch_order",stretch_order)
--- end
--- if shrink_order and shrink_order ~= 0 then
--- setfield(s,"shrink_order",shrink_order)
--- end
--- return s
--- end
-
function nutpool.gluespec(width,stretch,shrink,stretch_order,shrink_order)
-- maybe setglue
local s = copy_nut(glue_spec)
@@ -270,27 +258,6 @@ function nutpool.gluespec(width,stretch,shrink,stretch_order,shrink_order)
return s
end
--- local function someskip(skip,width,stretch,shrink,stretch_order,shrink_order)
--- -- maybe setglue
--- local n = copy_nut(skip)
--- if width and width ~= 0 then
--- setfield(n,"width",width)
--- end
--- if stretch and stretch ~= 0 then
--- setfield(n,"stretch",stretch)
--- end
--- if shrink and shrink ~= 0 then
--- setfield(n,"shrink",shrink)
--- end
--- if stretch_order and stretch_order ~= 0 then
--- setfield(n,"stretch_order",stretch_order)
--- end
--- if shrink_order and shrink_order ~= 0 then
--- setfield(n,"shrink_order",shrink_order)
--- end
--- return n
--- end
-
local function someskip(skip,width,stretch,shrink,stretch_order,shrink_order)
-- maybe setglue
local n = copy_nut(skip)
@@ -300,18 +267,6 @@ local function someskip(skip,width,stretch,shrink,stretch_order,shrink_order)
return n
end
--- function nutpool.stretch(a,b)
--- local n = copy_nut(glue)
--- if b then
--- setfield(n,"stretch",a)
--- setfield(n,"stretch_order",b)
--- else
--- setfield(n,"stretch",1)
--- setfield(n,"stretch_order",a or 1)
--- end
--- return n
--- end
-
function nutpool.stretch(a,b)
-- width stretch shrink stretch_order shrink_order
local n = copy_nut(glue)
@@ -322,18 +277,6 @@ function nutpool.stretch(a,b)
return n
end
--- function nutpool.shrink(a,b)
--- local n = copy_nut(glue)
--- if b then
--- setfield(n,"shrink",a)
--- setfield(n,"shrink_order",b)
--- else
--- setfield(n,"shrink",1)
--- setfield(n,"shrink_order",a or 1)
--- end
--- return n
--- end
-
function nutpool.shrink(a,b)
local n = copy_nut(glue)
if not b then
@@ -347,23 +290,6 @@ function nutpool.glue(width,stretch,shrink,stretch_order,shrink_order)
return someskip(glue,width,stretch,shrink,stretch_order,shrink_order)
end
--- function nutpool.negatedglue(glue)
--- local n = copy_nut(glue)
--- local width = getfield(n,"width")
--- local stretch = getfield(n,"stretch")
--- local shrink = getfield(n,"shrink")
--- if width and width ~= 0 then
--- setfield(n,"width", -width)
--- end
--- if stretch and stretch ~= 0 then
--- setfield(n,"stretch",-stretch)
--- end
--- if shrink and shrink ~= 0 then
--- setfield(n,"shrink", -shrink)
--- end
--- return n
--- end
-
function nutpool.negatedglue(glue)
local n = copy_nut(glue)
local width, stretch, shrink = getglue(n)
@@ -387,13 +313,19 @@ function nutpool.baselineskip(width,stretch,shrink)
return someskip(baselineskip,width,stretch,shrink)
end
-function nutpool.disc()
- return copy_nut(disc)
+function nutpool.disc(pre,post,replace)
+ local d = copy_nut(disc)
+ if pre or post or replace then
+ setdisc(d,pre,post,replace)
+ end
+ return d
end
function nutpool.textdir(dir)
local t = copy_nut(textdir)
- setfield(t,"dir",dir)
+ if dir then
+ setdir(t,dir)
+ end
return t
end
@@ -403,7 +335,7 @@ function nutpool.rule(width,height,depth,dir) -- w/h/d == nil will let them adap
setwhd(n,width,height,depth)
end
if dir then
- setfield(n,"dir",dir)
+ setdir(n,dir)
end
return n
end
@@ -414,7 +346,7 @@ function nutpool.emptyrule(width,height,depth,dir) -- w/h/d == nil will let them
setwhd(n,width,height,depth)
end
if dir then
- setfield(n,"dir",dir)
+ setdir(n,dir)
end
return n
end
@@ -425,7 +357,7 @@ function nutpool.userrule(width,height,depth,dir) -- w/h/d == nil will let them
setwhd(n,width,height,depth)
end
if dir then
- setfield(n,"dir",dir)
+ setdir(n,dir)
end
return n
end
@@ -448,7 +380,7 @@ function nutpool.leftmarginkern(glyph,width)
setfield(n,"glyph",glyph)
end
if width and width ~= 0 then
- setfield(n,"width",width)
+ setwidth(n,width)
end
return n
end
@@ -463,7 +395,7 @@ function nutpool.rightmarginkern(glyph,width)
setfield(n,"glyph",glyph)
end
if width and width ~= 0 then
- setfield(n,"width",width)
+ setwidth(n,width)
end
return n
end
@@ -485,7 +417,7 @@ local function new_hlist(list,width,height,depth,shift)
setwhd(n,width,height,depth)
end
if shift and shift ~= 0 then
- setfield(n,"shift",shift)
+ setshift(n,shift)
end
return n
end
@@ -499,7 +431,7 @@ local function new_vlist(list,width,height,depth,shift)
setwhd(n,width,height,depth)
end
if shift and shift ~= 0 then
- setfield(n,"shift",shift)
+ setshift(n,shift)
end
return n
end
diff --git a/tex/context/base/mkiv/node-rul.lua b/tex/context/base/mkiv/node-rul.lua
index 97100c896..8646fe447 100644
--- a/tex/context/base/mkiv/node-rul.lua
+++ b/tex/context/base/mkiv/node-rul.lua
@@ -19,9 +19,10 @@ if not modules then modules = { } end modules ['node-rul'] = {
local attributes = attributes
local nodes = nodes
-local tasks = nodes.tasks
local properties = nodes.properties
+local enableaction = nodes.tasks.enableaction
+
local nuts = nodes.nuts
local tonode = nuts.tonode
local tonut = nuts.tonut
@@ -39,6 +40,12 @@ local setattr = nuts.setattr
local getfont = nuts.getfont
local getsubtype = nuts.getsubtype
local getlist = nuts.getlist
+local setwhd = nuts.setwhd
+local setdir = nuts.setdir
+local setattrlist = nuts.setattrlist
+local setshift = nuts.setshift
+local getwidth = nuts.getwidth
+local setwidth = nuts.setwidth
local flushlist = nuts.flush_list
local effective_glue = nuts.effective_glue
@@ -58,15 +65,9 @@ local listcodes = nodes.listcodes
local kerncodes = nodes.kerncodes
local glyph_code = nodecodes.glyph
-local disc_code = nodecodes.disc
-local rule_code = nodecodes.rule
-local boundary_code = nodecodes.boundary
local localpar_code = nodecodes.localpar
local dir_code = nodecodes.dir
-local math_code = nodecodes.math
local glue_code = nodecodes.glue
-local penalty_code = nodecodes.penalty
-local kern_code = nodecodes.kern
local hlist_code = nodecodes.hlist
local indent_code = listcodes.indent
@@ -103,13 +104,10 @@ local v_left = variables.left
local v_right = variables.right
local v_local = variables["local"]
local v_yes = variables.yes
-local v_all = variables.all
local v_foreground = variables.foreground
local fonthashes = fonts.hashes
local fontdata = fonthashes.identifiers
-local fontunicodes = fonthashes.unicodes
-local fontcharacters = fonthashes.characters
local fontresources = fonthashes.resources
local dimenfactor = fonts.helpers.dimenfactor
@@ -139,7 +137,7 @@ local function userrule(t,noattributes)
if noattributes == false or noattributes == nil then
-- avoid fuzzy ones
else
- setfield(r,"attr",current_attr())
+ setattrlist(r,current_attr())
end
properties[r] = t
return tonode(r)
@@ -349,14 +347,9 @@ rules.handler = function(head)
end
function rules.enable()
- tasks.enableaction("shipouts","nodes.rules.handler")
+ enableaction("shipouts","nodes.rules.handler")
end
--- elsewhere:
---
--- tasks.appendaction ("shipouts", "normalizers", "nodes.rules.handler")
--- tasks.disableaction("shipouts", "nodes.rules.handler") -- only kick in when used
-
local trace_shifted = false trackers.register("nodes.shifting", function(v) trace_shifted = v end)
local report_shifted = logs.reporter("nodes","shifting")
@@ -384,7 +377,7 @@ local function flush_shifted(head,first,last,data,level,parent,strip) -- not tha
setprev(first)
setnext(last)
local width, height, depth = list_dimensions(parent,first,next)
- local list = hpack_nodes(first,width,"exactly")
+ local list = hpack_nodes(first,width,"exactly") -- we can use a simple pack
if first == head then
head = list
end
@@ -395,9 +388,8 @@ local function flush_shifted(head,first,last,data,level,parent,strip) -- not tha
setlink(list,next)
end
local raise = data.dy * dimenfactor(data.unit,fontdata[getfont(first)])
- setfield(list,"shift",raise)
- setfield(list,"height",height)
- setfield(list,"depth",depth)
+ setshift(list,raise)
+ setwhd(list,width,height,depth)
if trace_shifted then
report_shifted("width %p, nodes %a, text %a",width,n_tostring(first,last),n_tosequence(first,last,true))
end
@@ -409,7 +401,7 @@ local process = nodes.processwords
nodes.shifts.handler = function(head) return process(a_shifted,data,flush_shifted,head) end
function nodes.shifts.enable()
- tasks.enableaction("shipouts","nodes.shifts.handler")
+ enableaction("shipouts","nodes.shifts.handler")
end
-- linefillers
@@ -445,7 +437,7 @@ local function linefiller(current,data,width,location)
ca = ca,
ta = ta,
option = location,
- direction = getfield(current,"dir"),
+ direction = getdir(current),
})
else
local linefiller = new_rule(width,height,depth)
@@ -471,6 +463,7 @@ local function find_attr(head,attr)
end
function nodes.linefillers.handler(head)
+-- local current = tonut(head) -- when we hook into the contributers
for current in traverse_id(hlist_code,tonut(head)) do
if getsubtype(current) == line_code then
local list = getlist(current)
@@ -523,16 +516,16 @@ function nodes.linefillers.handler(head)
head = getnext(head)
end
if head then
- local indentation = iskip and getfield(iskip,"width") or 0
- local leftfixed = lskip and getfield(lskip,"width") or 0
+ local indentation = iskip and getwidth(iskip) or 0
+ local leftfixed = lskip and getwidth(lskip) or 0
local lefttotal = lskip and effective_glue(lskip,current) or 0
local width = lefttotal - (leftlocal and leftfixed or 0) + indentation - distance
if width > threshold then
if iskip then
- setfield(iskip,"width",0)
+ setwidth(iskip,0)
end
if lskip then
- setglue(lskip,leftlocal and getfield(lskip,"width") or nil)
+ setglue(lskip,leftlocal and getwidth(lskip) or nil)
if distance > 0 then
insert_node_after(list,lskip,new_kern(distance))
end
@@ -563,9 +556,9 @@ function nodes.linefillers.handler(head)
tail = getprev(tail)
end
if tail then
- local rightfixed = rskip and getfield(rskip,"width") or 0
+ local rightfixed = rskip and getwidth(rskip) or 0
local righttotal = rskip and effective_glue(rskip,current) or 0
- local parfixed = pskip and getfield(pskip,"width") or 0
+ local parfixed = pskip and getwidth(pskip) or 0
local partotal = pskip and effective_glue(pskip,current) or 0
local width = righttotal - (rightlocal and rightfixed or 0) + partotal - distance
if width > threshold then
@@ -573,7 +566,7 @@ function nodes.linefillers.handler(head)
setglue(pskip)
end
if rskip then
- setglue(rskip,rightlocal and getfield(rskip,"width") or nil)
+ setglue(rskip,rightlocal and getwidth(rskip) or nil)
if distance > 0 then
insert_node_before(list,rskip,new_kern(distance))
end
@@ -600,7 +593,7 @@ local enable = false
function nodes.linefillers.enable()
if not enable then
-- we could now nil it
- tasks.enableaction("finalizers","nodes.linefillers.handler")
+ enableaction("finalizers","nodes.linefillers.handler")
enable = true
end
end
diff --git a/tex/context/base/mkiv/node-ser.lua b/tex/context/base/mkiv/node-ser.lua
index 847db7a15..f1be21f84 100644
--- a/tex/context/base/mkiv/node-ser.lua
+++ b/tex/context/base/mkiv/node-ser.lua
@@ -26,7 +26,6 @@ local nodecodes = nodes.nodecodes
local subtcodes = nodes.codes
local noadcodes = nodes.noadcodes
local getfields = nodes.fields
-local nodekeys = nodes.keys
local tonode = nodes.tonode
diff --git a/tex/context/base/mkiv/node-tra.lua b/tex/context/base/mkiv/node-tra.lua
index b3b4311e7..0d3192559 100644
--- a/tex/context/base/mkiv/node-tra.lua
+++ b/tex/context/base/mkiv/node-tra.lua
@@ -47,10 +47,14 @@ local getsubtype = nuts.getsubtype
local getlist = nuts.getlist
local getdisc = nuts.getdisc
local setattr = nuts.setattr
+local getglue = nuts.getglue
local isglyph = nuts.isglyph
+local getcomponents = nuts.getcomponents
+local getdir = nuts.getdir
+local getwidth = nuts.getwidth
local flush_list = nuts.flush_list
-local count_nodes = nuts.count
+local count_nodes = nuts.countall
local used_nodes = nuts.usedlist
local traverse_by_id = nuts.traverse_id
@@ -121,6 +125,7 @@ function nodes.handlers.checkforleaks(sparse)
end
local f_sequence = formatters["U+%04X:%s"]
+local f_subrange = formatters["[[ %s ][ %s ][ %s ]]"]
local function tosequence(start,stop,compact)
if start then
@@ -131,7 +136,7 @@ local function tosequence(start,stop,compact)
local c, id = isglyph(start)
if c then
if compact then
- local components = getfield(start,"components")
+ local components = getcomponents(start)
if components then
t[#t+1] = tosequence(components,nil,compact)
else
@@ -140,6 +145,9 @@ local function tosequence(start,stop,compact)
else
t[#t+1] = f_sequence(c,utfchar(c))
end
+ elseif id == disc_code then
+ local pre, post, replace = getdisc(start)
+ t[#t+1] = f_subrange(pre and tosequence(pre),post and tosequence(post),replace and tosequence(replace))
elseif id == rule_code then
if compact then
t[#t+1] = "|"
@@ -147,7 +155,7 @@ local function tosequence(start,stop,compact)
t[#t+1] = nodecodes[id]
end
elseif id == dir_code or id == localpar_code then
- t[#t+1] = "[" .. getfield(start,"dir") .. "]"
+ t[#t+1] = "[" .. getdir(start) .. "]"
elseif compact then
t[#t+1] = "[]"
else
@@ -310,7 +318,7 @@ local function listtoutf(h,joiner,textonly,last,nodisc)
end
elseif textonly then
if id == glue_code then
- if getfield(h,"width") > 0 then
+ if getwidth(h) > 0 then
w[#w+1] = " "
end
elseif id == hlist_code or id == vlist_code then
@@ -375,7 +383,7 @@ local function nodetodimen(n)
n = tonut(n)
local id = getid(n)
if id == kern_code then
- local width = getfield(n,"width")
+ local width = getwidth(n)
if width == 0 then
return "0pt"
else
@@ -384,11 +392,10 @@ local function nodetodimen(n)
elseif id ~= glue_code then
return "0pt"
end
- local stretch_order = getfield(n,"stretch_order")
- local shrink_order = getfield(n,"shrink_order")
- local stretch = getfield(n,"stretch") / 65536
- local shrink = getfield(n,"shrink") / 65536
- local width = getfield(n,"width") / 65536
+ local width, stretch, shrink, stretch_order, shrink_order = getglue(n)
+ stretch = stretch / 65536
+ shrink = shrink / 65536
+ width = width / 65536
if stretch_order ~= 0 then
if shrink_order ~= 0 then
return f_f_f(width,stretch,fillorders[stretch_order],shrink,fillorders[shrink_order])
diff --git a/tex/context/base/mkiv/node-tsk.lua b/tex/context/base/mkiv/node-tsk.lua
index 56a4b18ef..4dcbb27bd 100644
--- a/tex/context/base/mkiv/node-tsk.lua
+++ b/tex/context/base/mkiv/node-tsk.lua
@@ -30,6 +30,20 @@ local sequencers = utilities.sequencers
local compile = sequencers.compile
local nodeprocessor = sequencers.nodeprocessor
+local newsequencer = sequencers.new
+
+local appendgroup = sequencers.appendgroup
+----- prependgroup = sequencers.prependgroup
+----- replacegroup = sequencers.replacegroup
+local enablegroup = sequencers.enablegroup
+local disablegroup = sequencers.disablegroup
+
+local appendaction = sequencers.appendaction
+local prependaction = sequencers.prependaction
+local replaceaction = sequencers.replaceaction
+local enableaction = sequencers.enableaction
+local disableaction = sequencers.disableaction
+
local frozengroups = "no"
function tasks.freeze(kind)
@@ -41,7 +55,7 @@ function tasks.new(specification) -- was: name,arguments,list
local arguments = specification.arguments or 0
local sequence = specification.sequence
if name and sequence then
- local tasklist = sequencers.new {
+ local tasklist = newsequencer {
-- we can move more to the sequencer now .. todo
}
tasksdata[name] = {
@@ -53,7 +67,7 @@ function tasks.new(specification) -- was: name,arguments,list
processor = specification.processor or nodeprocessor
}
for l=1,#sequence do
- sequencers.appendgroup(tasklist,sequence[l])
+ appendgroup(tasklist,sequence[l])
end
end
end
@@ -104,7 +118,7 @@ end
function tasks.enableaction(name,action)
local data = valid(name)
if data then
- sequencers.enableaction(data.list,action)
+ enableaction(data.list,action)
data.runner = false
end
end
@@ -112,7 +126,7 @@ end
function tasks.disableaction(name,action)
local data = valid(name)
if data then
- sequencers.disableaction(data.list,action)
+ disableaction(data.list,action)
data.runner = false
end
end
@@ -120,23 +134,30 @@ end
function tasks.replaceaction(name,group,oldaction,newaction)
local data = valid(name)
if data then
- sequencers.replaceaction(data.list,group,oldaction,newaction)
+ replaceaction(data.list,group,oldaction,newaction)
data.runner = false
end
end
-function tasks.setaction(name,action,value)
- if value then
- tasks.enableaction(name,action)
- else
- tasks.disableaction(name,action)
+do
+
+ local enableaction = tasks.enableaction
+ local disableaction = tasks.disableaction
+
+ function tasks.setaction(name,action,value)
+ if value then
+ enableaction(name,action)
+ else
+ disableaction(name,action)
+ end
end
+
end
function tasks.enablegroup(name,group)
local data = validgroup(name,"enable group")
if data then
- sequencers.enablegroup(data.list,group)
+ enablegroup(data.list,group)
data.runner = false
end
end
@@ -144,7 +165,7 @@ end
function tasks.disablegroup(name,group)
local data = validgroup(name,"disable group")
if data then
- sequencers.disablegroup(data.list,group)
+ disablegroup(data.list,group)
data.runner = false
end
end
@@ -152,7 +173,7 @@ end
function tasks.appendaction(name,group,action,where,kind)
local data = validgroup(name,"append action")
if data then
- sequencers.appendaction(data.list,group,action,where,kind)
+ appendaction(data.list,group,action,where,kind)
data.runner = false
end
end
@@ -160,7 +181,7 @@ end
function tasks.prependaction(name,group,action,where,kind)
local data = validgroup(name,"prepend action")
if data then
- sequencers.prependaction(data.list,group,action,where,kind)
+ prependaction(data.list,group,action,where,kind)
data.runner = false
end
end
@@ -168,7 +189,7 @@ end
function tasks.removeaction(name,group,action)
local data = validgroup(name,"remove action")
if data then
- sequencers.removeaction(data.list,group,action)
+ removeaction(data.list,group,action)
data.runner = false
end
end
@@ -366,6 +387,7 @@ tasks.new {
tasks.new {
name = "shipouts",
arguments = 0,
+ -- nostate = true, -- maybe but only for main ones so little gain
processor = nodeprocessor,
sequence = {
"before", -- for users
@@ -418,3 +440,15 @@ tasks.new {
-- "after", -- for users
-- }
-- }
+
+tasks.new {
+ name = "contributers",
+ arguments = 1,
+ processor = nodeprocessor,
+ sequence = {
+ "before", -- for users
+ "normalizers",
+ "after", -- for users
+ }
+}
+
diff --git a/tex/context/base/mkiv/node-tst.lua b/tex/context/base/mkiv/node-tst.lua
index 4832c048c..1109f28a3 100644
--- a/tex/context/base/mkiv/node-tst.lua
+++ b/tex/context/base/mkiv/node-tst.lua
@@ -32,6 +32,9 @@ local getprev = nuts.getprev
local getid = nuts.getid
local getchar = nuts.getchar
local getsubtype = nuts.getsubtype
+local getkern = nuts.getkern
+local getpenalty = nuts.getpenalty
+local getwidth = nuts.getwidth
local find_node_tail = nuts.tail
@@ -39,11 +42,11 @@ function nuts.leftmarginwidth(n) -- todo: three values
while n do
local id = getid(n)
if id == glue_code then
- return getsubtype(n) == leftskip_code and getfield(n,"width") or 0
+ return getsubtype(n) == leftskip_code and getwidth(n) or 0
elseif id == whatsit_code then
n = getnext(n)
elseif id == hlist_code then
- return getfield(n,"width")
+ return getwidth(n)
else
break
end
@@ -57,7 +60,7 @@ function nuts.rightmarginwidth(n)
while n do
local id = getid(n)
if id == glue_code then
- return getsubtype(n) == rightskip_code and getfield(n,"width") or 0
+ return getsubtype(n) == rightskip_code and getwidth(n) or 0
elseif id == whatsit_code then
n = getprev(n)
else
@@ -72,10 +75,9 @@ function nuts.somespace(n,all)
if n then
local id = getid(n)
if id == glue_code then
- return (all or ((getfield(n,"width") or 0) ~= 0)) and glue_code -- temp: or 0
- -- return (all or (getfield(n,"width") ~= 0)) and glue_code
+ return (all or (getwidth(n) ~= 0)) and glue_code -- temp: or 0
elseif id == kern_code then
- return (all or (getfield(n,"kern") ~= 0)) and kern
+ return (all or (getkern(n) ~= 0)) and kern
elseif id == glyph_code then
local category = chardata[getchar(n)].category
-- maybe more category checks are needed
@@ -90,7 +92,7 @@ function nuts.somepenalty(n,value)
local id = getid(n)
if id == penalty_code then
if value then
- return getfield(n,"penalty") == value
+ return getpenalty(n) == value
else
return true
end
diff --git a/tex/context/base/mkiv/node-typ.lua b/tex/context/base/mkiv/node-typ.lua
index efabe657b..06d0f13c2 100644
--- a/tex/context/base/mkiv/node-typ.lua
+++ b/tex/context/base/mkiv/node-typ.lua
@@ -18,6 +18,7 @@ local tonut = nuts.tonut
local setfield = nuts.setfield
local setlink = nuts.setlink
local setchar = nuts.setchar
+----- setattrlist = nuts.setattrlist
local getfield = nuts.getfield
local getfont = nuts.getfont
@@ -42,7 +43,7 @@ local function tonodes(str,fontid,spacing,templateglyph) -- quick and dirty
if not fontid then
if templateglyph then
fontid = getfont(templateglyph)
- -- attrid = getfield(templateglyph,"attr")
+ -- attrid = setattrlist(templateglyph)
else
fontid = currentfont()
-- attrid = current_attr()
@@ -74,10 +75,10 @@ local function tonodes(str,fontid,spacing,templateglyph) -- quick and dirty
if not next then
-- nothing
elseif not head then
--- setfield(next,"attr",attrid)
+ -- setattrlist(next,attrid)
head = next
else
--- setfield(next,"attr",attrid)
+ -- setattrlist(next,attrid)
setlink(prev,next)
end
prev = next
diff --git a/tex/context/base/mkiv/pack-rul.lua b/tex/context/base/mkiv/pack-rul.lua
index 3279dca51..30eda7dd2 100644
--- a/tex/context/base/mkiv/pack-rul.lua
+++ b/tex/context/base/mkiv/pack-rul.lua
@@ -11,8 +11,6 @@ if not modules then modules = { } end modules ['pack-rul'] = {
--ldx]]--
-- we need to be careful with display math as it uses shifts
--- challenge: adapt glue_set
--- setfield(h,"glue_set", getfield(h,"glue_set") * getfield(h,"width")/maxwidth -- interesting ... doesn't matter much
-- \framed[align={lohi,middle}]{$x$}
-- \framed[align={lohi,middle}]{$ $}
@@ -45,6 +43,10 @@ local getwhd = nuts.getwhd
local getid = nuts.getid
local getsubtype = nuts.getsubtype
local getbox = nuts.getbox
+local getdir = nuts.getdir
+local setshift = nuts.setshift
+local setwidth = nuts.setwidth
+local getwidth = nuts.getwidth
local hpack = nuts.hpack
local traverse_id = nuts.traverse_id
@@ -68,7 +70,7 @@ local function doreshapeframedbox(n)
local maxwidth = 0
local totalwidth = 0
local averagewidth = 0
- local boxwidth = getfield(box,"width")
+ local boxwidth = getwidth(box)
if boxwidth ~= 0 then -- and h.subtype == vlist_code
local list = getlist(box)
if list then
@@ -84,7 +86,7 @@ local function doreshapeframedbox(n)
if repack then
local subtype = getsubtype(n)
if subtype == box_code or subtype == line_code then
- lastlinelength = list_dimensions(l,getfield(n,"dir"))
+ lastlinelength = list_dimensions(l,getdir(n))
else
lastlinelength = width
end
@@ -122,7 +124,7 @@ local function doreshapeframedbox(n)
if l then
local subtype = getsubtype(h)
if subtype == box_code or subtype == line_code then
- local p = hpack(l,maxwidth,'exactly',getfield(h,"dir")) -- multiple return value
+ local p = hpack(l,maxwidth,'exactly',getdir(h)) -- multiple return value
setfield(h,"glue_set",getfield(p,"glue_set"))
setfield(h,"glue_order",getfield(p,"glue_order"))
setfield(h,"glue_sign",getfield(p,"glue_sign"))
@@ -131,25 +133,25 @@ local function doreshapeframedbox(n)
elseif checkformath and subtype == equation_code then
-- display formulas use a shift
if nofnonzero == 1 then
- setfield(h,"shift",0)
+ setshift(h,0)
end
end
- setfield(h,"width",maxwidth)
+ setwidth(h,maxwidth)
end
end
end
-- if vdone then
-- for v in traverse_id(vlist_code,list) do
- -- local width = getfield(n,"width")
+ -- local width = getwidth(n)
-- if width > maxwidth then
- -- setfield(v,"width",maxwidth)
+ -- setwidth(v,maxwidth)
-- end
-- end
-- end
- setfield(box,"width",maxwidth)
+ setwidth(box,maxwidth)
averagewidth = noflines > 0 and totalwidth/noflines or 0
else -- e.g. empty math {$ $} or \hbox{} or ...
- setfield(box,"width",0)
+ setwidth(box,0)
end
end
end
@@ -166,7 +168,7 @@ local function doanalyzeframedbox(n)
local noflines = 0
local firstheight = nil
local lastdepth = nil
- if getfield(box,"width") ~= 0 then
+ if getwidth(box) ~= 0 then
local list = getlist(box)
if list then
local function check(n)
@@ -194,7 +196,7 @@ implement { name = "doreshapeframedbox", actions = doreshapeframedbox, arguments
implement { name = "doanalyzeframedbox", actions = doanalyzeframedbox, arguments = "integer" }
local function maxboxwidth(box)
- local boxwidth = getfield(box,"width")
+ local boxwidth = getwidth(box)
if boxwidth == 0 then
return 0
end
@@ -213,12 +215,12 @@ local function maxboxwidth(box)
if repack then
local subtype = getsubtype(n)
if subtype == box_code or subtype == line_code then
- lastlinelength = list_dimensions(l,getfield(n,"dir"))
+ lastlinelength = list_dimensions(l,getdir(n))
else
- lastlinelength = getfield(n,"width")
+ lastlinelength = getwidth(n)
end
else
- lastlinelength = getfield(n,"width")
+ lastlinelength = getwidth(n)
end
if lastlinelength > maxwidth then
maxwidth = lastlinelength
@@ -238,6 +240,6 @@ nodes.maxboxwidth = maxboxwidth
implement {
name = "themaxboxwidth",
- actions = function(n) context("%isp",maxboxwidth(getbox(n))) end,
+ actions = function(n) context("%rsp",maxboxwidth(getbox(n))) end, -- r = rounded
arguments = "integer"
}
diff --git a/tex/context/base/mkiv/page-cst.lua b/tex/context/base/mkiv/page-cst.lua
index cd3b63c5d..03707a312 100644
--- a/tex/context/base/mkiv/page-cst.lua
+++ b/tex/context/base/mkiv/page-cst.lua
@@ -52,6 +52,10 @@ local setsubtype = nuts.setsubtype
local setbox = nuts.setbox
local getwhd = nuts.getwhd
local setwhd = nuts.setwhd
+local getkern = nuts.getkern
+local getpenalty = nuts.getpenalty
+local getwidth = nuts.getwidth
+local getheight = nuts.getheight
local getnext = nuts.getnext
local getprev = nuts.getprev
@@ -337,11 +341,7 @@ function columnsets.prepareflush(name)
for r=1,nofrows-1 do
setlink(column[r],column[r+1])
end
- local v = new_vlist(column[1])
- setfield(v,"height",height)
- -- setfield(v,"depth",linedepth)
- setfield(v,"width",widths[c])
- columns[c] = v
+ columns[c] = new_vlist(column[1],widths[c],height,0) -- linedepth
end
--
texsetcount("c_page_grid_first_column",firstcolumn)
@@ -774,9 +774,9 @@ end
-- if line then
-- break
-- end
--- used = used + getfield(head,"width")
+-- used = used + getwidth(head)
-- elseif id == kern_code then
--- used = used + getfield(head,"kern")
+-- used = used + getkern(head)
-- elseif id == penalty_code then
-- end
-- if used > available then
@@ -813,18 +813,18 @@ local function checkroom(head,available,row)
if line then
break
end
- used = used + getfield(head,"width")
+ used = used + getwidth(head)
if used > available then
break
end
elseif id == kern_code then
- used = used + getfield(head,"kern")
+ used = used + getkern(head)
if used > available then
break
end
elseif id == penalty_code then
-- not good enough ... we need to look bakck too
- if getfield(head,"penalty") >= 10000 then
+ if getpenalty(head) >= 10000 then
line = false
else
break
@@ -862,9 +862,9 @@ end
-- if id == hlist_code or id == vlist_code or id == rule_code then -- <= rule_code
-- hd = getfield(head,"height") + getfield(head,"depth")
-- elseif id == glue_code then
--- hd = getfield(head,"width")
+-- hd = getwidth(head)
-- elseif id == kern_code then
--- hd = getfield(head,"kern")
+-- hd = getkern(head)
-- elseif id == penalty_code then
-- end
-- if used + hd > available then
@@ -919,7 +919,7 @@ local function findslice(dataset,head,available,column,row)
attempts = attempts + 1
texsetbox("scratchbox",tonode(new_vlist(copy)))
local done = splitbox("scratchbox",usedsize,"additional")
- local used = getfield(done,"height")
+ local used = getheight(done)
local rest = takebox("scratchbox")
if used > (usedsize+slack) then
if trace_detail then
@@ -943,7 +943,7 @@ local function findslice(dataset,head,available,column,row)
texsetbox("scratchbox",tonode(new_vlist(head)))
done = splitbox("scratchbox",usedsize,"additional")
rest = takebox("scratchbox")
- used = getfield(done,"height")
+ used = getheight(done)
if attempts > 1 then
used = available
end
@@ -1237,9 +1237,7 @@ function columnsets.setarea(t)
local column = t.c
local row = t.r
if column and row then
- setfield(box,"height",dataset.lineheight)
- setfield(box,"depth",dataset.linedepth)
- setfield(box,"width",dataset.widths[column])
+ setwhd(box,dataset.widths[column],dataset.lineheight,dataset.linedepth)
cells[column][row] = box
end
end
diff --git a/tex/context/base/mkiv/page-ins.mkiv b/tex/context/base/mkiv/page-ins.mkiv
index c91073a14..51f2a3c1c 100644
--- a/tex/context/base/mkiv/page-ins.mkiv
+++ b/tex/context/base/mkiv/page-ins.mkiv
@@ -55,7 +55,7 @@
\unexpanded\def\page_inserts_synchronize_registers
{\currentinsertionnumber\csname\??insertionnumber\currentinsertion\endcsname}
-% for practical reasone we still set these elsewhere but that might chaneg in the future
+% for practical reasons we still set these elsewhere but that might change in the future
%
% \global\count\currentinsertionnumber\numexpr\insertionparameter\c!factor/\insertionparameter\c!n\relax
% \global\skip \currentinsertionnumber\insertionparameter\c!distance \relax
@@ -65,7 +65,7 @@
\page_inserts_synchronize_registers
\to \everysetupinsertion
-\unexpanded\def\page_inserts_process#1% beware, this addapts currentinsertion !
+\unexpanded\def\page_inserts_process#1% beware, this adapts currentinsertion !
{\edef\currentinsertion{#1}%
\currentinsertionnumber\csname\??insertionnumber\currentinsertion\endcsname
\doprocessinsert\currentinsertionnumber} % old method
diff --git a/tex/context/base/mkiv/page-lin.lua b/tex/context/base/mkiv/page-lin.lua
index 011418063..8ec4ba5df 100644
--- a/tex/context/base/mkiv/page-lin.lua
+++ b/tex/context/base/mkiv/page-lin.lua
@@ -56,7 +56,7 @@ local line_code = listcodes.line
local a_displaymath = attributes.private('displaymath')
local a_linenumber = attributes.private('linenumber')
local a_linereference = attributes.private('linereference')
-local a_verbatimline = attributes.private('verbatimline')
+----- a_verbatimline = attributes.private('verbatimline')
local current_list = { }
local cross_references = { }
@@ -72,6 +72,10 @@ local setattr = nuts.setattr
local getlist = nuts.getlist
local getbox = nuts.getbox
local getfield = nuts.getfield
+----- getdir = nuts.getdir
+----- getwidth = nuts.getwidth
+local getheight = nuts.getheight
+local getdepth = nuts.getdepth
local setprop = nuts.setprop
local getprop = nuts.getprop
@@ -386,7 +390,7 @@ function boxed.stage_one(n,nested)
local subtype = getsubtype(n)
if subtype ~= line_code then
-- go on
- elseif getfield(n,"height") == 0 and getfield(n,"depth") == 0 then
+ elseif getheight(n) == 0 and getdepth(n) == 0 then
-- skip funny hlists -- todo: check line subtype
else
local a = lineisnumbered(n)
@@ -410,14 +414,14 @@ function boxed.stage_one(n,nested)
check_number(n,a,skip)
end
else
--- -- we now prevent nesting anyway .. maybe later we need to check again
--- local v = getattr(list,a_verbatimline)
--- if not v or v ~= last_v then
--- last_v = v
+ -- -- we now prevent nesting anyway .. maybe later we need to check again
+ -- local v = getattr(list,a_verbatimline)
+ -- if not v or v ~= last_v then
+ -- last_v = v
check_number(n,a,skip)
--- else
--- check_number(n,a,skip,true)
--- end
+ -- else
+ -- check_number(n,a,skip,true)
+ -- end
end
skip = false
end
@@ -480,10 +484,10 @@ function boxed.stage_two(n,m)
local li = current_list[i]
local n, m, ti = li[1], li[2], t[i]
if ti then
- -- local d = getfield(n,"dir")
+ -- local d = getdir(n)
-- local l = getlist(n)
-- if d == "TRT" then
- -- local w = getfield(n,"width")
+ -- local w = getwidth(n)
-- ti = hpack_nodes(linked_nodes(new_kern(-w),ti,new_kern(w)))
-- end
-- setnext(ti,l)
diff --git a/tex/context/base/mkiv/page-mix.lua b/tex/context/base/mkiv/page-mix.lua
index 6bbc434dd..524181c8e 100644
--- a/tex/context/base/mkiv/page-mix.lua
+++ b/tex/context/base/mkiv/page-mix.lua
@@ -47,14 +47,17 @@ local flushnode = nuts.flush
local concatnodes = nuts.concat
local slidenodes = nuts.slide -- ok here as we mess with prev links intermediately
-local getfield = nuts.getfield
local setfield = nuts.setfield
local setlink = nuts.setlink
local setlist = nuts.setlist
local setnext = nuts.setnext
local setprev = nuts.setprev
local setbox = nuts.setbox
+local setwhd = nuts.setwhd
+local setheight = nuts.setheight
+local setdepth = nuts.setdepth
+local getfield = nuts.getfield
local getnext = nuts.getnext
local getprev = nuts.getprev
local getid = nuts.getid
@@ -63,10 +66,11 @@ local getsubtype = nuts.getsubtype
local getbox = nuts.getbox
local getattribute = nuts.getattribute
local getwhd = nuts.getwhd
-local setwhd = nuts.setwhd
-
-local texgetcount = tex.getcount
-local texgetglue = tex.getglue
+local getkern = nuts.getkern
+local getpenalty = nuts.getpenalty
+local getwidth = nuts.getwidth
+local getheight = nuts.getheight
+local getdepth = nuts.getdepth
local theprop = nuts.theprop
@@ -119,7 +123,7 @@ local function collectinserts(result,nxt,nxtid)
if nxtid == insert_code then
i = i + 1
result.i = i
- inserttotal = inserttotal + getfield(nxt,"height") -- height includes depth
+ inserttotal = inserttotal + getheight(nxt) -- height includes depth
local s = getsubtype(nxt)
local c = inserts[s]
if trace_detail then
@@ -172,15 +176,15 @@ local function discardtopglue(current,discarded)
while current do
local id = getid(current)
if id == glue_code then
- size = size + getfield(current,"width")
+ size = size + getwidth(current)
discarded[#discarded+1] = current
current = getnext(current)
elseif id == penalty_code then
- if getfield(current,"penalty") == forcedbreak then
+ if getpenalty(current) == forcedbreak then
discarded[#discarded+1] = current
current = getnext(current)
while current and getid(current) == glue_code do
- size = size + getfield(current,"width")
+ size = size + getwidth(current)
discarded[#discarded+1] = current
current = getnext(current)
end
@@ -210,7 +214,7 @@ local function stripbottomglue(results,discarded)
end
local id = getid(t)
if id == penalty_code then
- if getfield(t,"penalty") == forcedbreak then
+ if getpenalty(t) == forcedbreak then
break
else
discarded[#discarded+1] = t
@@ -219,7 +223,7 @@ local function stripbottomglue(results,discarded)
end
elseif id == glue_code then
discarded[#discarded+1] = t
- local width = getfield(t,"width")
+ local width = getwidth(t)
if trace_state then
report_state("columns %s, discarded bottom glue %p",i,width)
end
@@ -256,8 +260,8 @@ local function preparesplit(specification) -- a rather large function
slidenodes(head) -- we can have set prev's to nil to prevent backtracking
local discarded = { }
local originalhead = head
- local originalwidth = specification.originalwidth or getfield(list,"width")
- local originalheight = specification.originalheight or getfield(list,"height")
+ local originalwidth = specification.originalwidth or getwidth(list)
+ local originalheight = specification.originalheight or getheight(list)
local current = head
local skipped = 0
local height = 0
@@ -480,7 +484,7 @@ local function preparesplit(specification) -- a rather large function
head = current
local function process_skip(current,nxt)
- local advance = getfield(current,"width")
+ local advance = getwidth(current)
if advance ~= 0 then
local state, skipped = checked(advance,"glue")
if trace_state then
@@ -515,7 +519,7 @@ local function preparesplit(specification) -- a rather large function
end
local function process_kern(current,nxt)
- local advance = getfield(current,"kern")
+ local advance = getkern(current)
if advance ~= 0 then
local state, skipped = checked(advance,"kern")
if trace_state then
@@ -538,7 +542,7 @@ local function preparesplit(specification) -- a rather large function
local function process_rule(current,nxt)
-- simple variant of h|vlist
- local advance = getfield(current,"height") -- + getfield(current,"depth")
+ local advance = getheight(current) -- + getdepth(current)
if advance ~= 0 then
local state, skipped = checked(advance,"rule")
if trace_state then
@@ -556,7 +560,7 @@ local function preparesplit(specification) -- a rather large function
-- else
-- height = height + currentskips
-- end
- depth = getfield(current,"depth")
+ depth = getdepth(current)
skip = 0
end
lastcontent = current
@@ -569,7 +573,7 @@ local function preparesplit(specification) -- a rather large function
-- [chapter] [penalty] [section] [penalty] [first line]
local function process_penalty(current,nxt)
- local penalty = getfield(current,"penalty")
+ local penalty = getpenalty(current)
if penalty == 0 then
unlock(penalty)
elseif penalty == forcedbreak then
@@ -783,11 +787,11 @@ local function finalize(result)
local l = list[i]
local h = new_hlist()
t[i] = h
- setlist(h,getfield(l,"head"))
+ setlist(h,getlist(l))
local wd, ht, dp = getwhd(l)
-- here ht is still ht + dp !
- setwhd(h,getfield(h,"width"),ht,dp)
- setfield(l,"head",nil)
+ setwhd(h,getwidth(h),ht,dp)
+ setlist(l)
end
setprev(t[1]) -- needs checking
setnext(t[#t]) -- needs checking
@@ -946,9 +950,7 @@ local function getsplit(result,n)
dp = result.depth
end
- setfield(v,"width",wd)
- setfield(v,"height",ht)
- setfield(v,"depth",dp)
+ setwhd(v,wd,ht,dp)
if trace_state then
local id = getid(h)
@@ -962,9 +964,9 @@ local function getsplit(result,n)
for c, list in next, r.inserts do
local l = concatnodes(list)
-for i=1,#list-1 do
- setfield(list[i],"depth",0)
-end
+ for i=1,#list-1 do
+ setdepth(list[i],0)
+ end
local b = vpack(l) -- multiple arguments, todo: fastvpack
-- setbox("global",c,b)
diff --git a/tex/context/base/mkiv/page-str.lua b/tex/context/base/mkiv/page-str.lua
index a254e9d7d..4aeffffd8 100644
--- a/tex/context/base/mkiv/page-str.lua
+++ b/tex/context/base/mkiv/page-str.lua
@@ -28,6 +28,8 @@ local vpack_node_list = nodes.vpack
local settings_to_array = utilities.parsers.settings_to_array
+local enableaction = nodes.tasks.enableaction
+
local texgetdimen = tex.getdimen
local texgetbox = tex.getbox
@@ -233,7 +235,7 @@ tasks.appendaction("mvlbuilders", "normalizers", "streams.collect")
tasks.disableaction("mvlbuilders", "streams.collect")
function streams.initialize()
- tasks.enableaction ("mvlbuilders", "streams.collect")
+ enableaction("mvlbuilders","streams.collect")
function streams.initialize() end
end
@@ -241,8 +243,8 @@ end
-- todo: better names, enable etc
implement {
- name = "initializestream",
- actions = streams.initialize,
+ name = "initializestream",
+ actions = streams.initialize,
onlyonce = true,
}
diff --git a/tex/context/base/mkiv/publ-sor.lua b/tex/context/base/mkiv/publ-sor.lua
index 218d11093..30a0d9bdd 100644
--- a/tex/context/base/mkiv/publ-sor.lua
+++ b/tex/context/base/mkiv/publ-sor.lua
@@ -217,6 +217,7 @@ local function sortsequence(dataset,list,sorttype)
if type(action) == "function" then
local valid = action(dataset,list,method)
if valid and #valid > 0 then
+-- sorters.setlanguage(options.language,options.method)
sorters.sort(valid,compare)
return valid
else
diff --git a/tex/context/base/mkiv/scrn-fld.mkvi b/tex/context/base/mkiv/scrn-fld.mkvi
index a92abebc5..d69e7beb9 100644
--- a/tex/context/base/mkiv/scrn-fld.mkvi
+++ b/tex/context/base/mkiv/scrn-fld.mkvi
@@ -246,7 +246,6 @@
\fi
layer {\fieldbodyparameter\c!fieldlayer}%
option {\fieldbodyparameter\c!option}%
- align {\fieldbodyparameter\c!align}%
clickin {\fieldbodyparameter\c!clickin}%
clickout {\fieldbodyparameter\c!clickout}%
regionin {\fieldbodyparameter\c!regionin}%
diff --git a/tex/context/base/mkiv/scrp-cjk.lua b/tex/context/base/mkiv/scrp-cjk.lua
index b919098f1..d2ec201ca 100644
--- a/tex/context/base/mkiv/scrp-cjk.lua
+++ b/tex/context/base/mkiv/scrp-cjk.lua
@@ -31,6 +31,7 @@ local getchar = nuts.getchar
local getid = nuts.getid
local getattr = nuts.getattr
local getsubtype = nuts.getsubtype
+local getwidth = nuts.getwidth
local getfield = nuts.getfield
local setchar = nuts.setchar
@@ -958,7 +959,7 @@ local function process(head,first,last)
local subtype = getsubtype(first)
if subtype == userskip_code or subtype == spaceskip_code or subtype == xspaceskip_code then
-- for the moment no distinction possible between space and userskip
- local w = getfield(first,"width")
+ local w = getwidth(first)
local s = spacedata[getfont(p)]
if w == s then -- could be option
if trace_details then
diff --git a/tex/context/base/mkiv/spac-adj.lua b/tex/context/base/mkiv/spac-adj.lua
index bebc15b88..3db59881b 100644
--- a/tex/context/base/mkiv/spac-adj.lua
+++ b/tex/context/base/mkiv/spac-adj.lua
@@ -8,15 +8,17 @@ if not modules then modules = { } end modules ['spac-adj'] = {
-- sort of obsolete code
-local a_vadjust = attributes.private('graphicvadjust')
+local a_vadjust = attributes.private('graphicvadjust')
-local nodecodes = nodes.nodecodes
+local nodecodes = nodes.nodecodes
-local hlist_code = nodecodes.hlist
-local vlist_code = nodecodes.vlist
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
-local remove_node = nodes.remove
-local hpack_node = node.hpack
+local remove_node = nodes.remove
+local hpack_node = node.hpack
+
+local enableaction = nodes.tasks.enableaction
function nodes.handlers.graphicvadjust(head,groupcode) -- we can make an actionchain for mvl only
if groupcode == "" then -- mvl only
@@ -60,6 +62,6 @@ interfaces.implement {
name = "enablegraphicvadjust",
onlyonce = true,
actions = function()
- nodes.tasks.enableaction("finalizers","nodes.handlers.graphicvadjust")
+ enableaction("finalizers","nodes.handlers.graphicvadjust")
end
}
diff --git a/tex/context/base/mkiv/spac-ali.lua b/tex/context/base/mkiv/spac-ali.lua
index dc206a2a2..bc77090cf 100644
--- a/tex/context/base/mkiv/spac-ali.lua
+++ b/tex/context/base/mkiv/spac-ali.lua
@@ -19,18 +19,18 @@ local tonode = nuts.tonode
local tonut = nuts.tonut
local getfield = nuts.getfield
-local setfield = nuts.setfield
local getnext = nuts.getnext
local getprev = nuts.getprev
local getid = nuts.getid
local getlist = nuts.getlist
local setlist = nuts.setlist
-local getattr = nuts.getattr
-local setattr = nuts.setattr
+local setlink = nuts.setlink
+local takeattr = nuts.takeattr
local getsubtype = nuts.getsubtype
+local getwidth = nuts.getwidth
+local findtail = nuts.tail
local hpack_nodes = nuts.hpack
-local linked_nodes = nuts.linked
local unsetvalue = attributes.unsetvalue
@@ -71,7 +71,7 @@ local function handler(head,leftpage,realpageno)
local id = getid(current)
if id == hlist_code then
if getsubtype(current) == line_code then
- local a = getattr(current,a_realign)
+ local a = takeattr(current,a_realign)
if not a or a == 0 then
-- skip
else
@@ -87,12 +87,16 @@ local function handler(head,leftpage,realpageno)
action = leftpage and 2 or 1
end
if action == 1 then
- setlist(current,hpack_nodes(linked_nodes(getlist(current),new_stretch(3)),getfield(current,"width"),"exactly"))
+ local head = getlist(current)
+ setlink(findtail(head),new_stretch(3)) -- append
+ setlist(current,hpack_nodes(head,getwidth(current),"exactly"))
if trace_realign then
report_realign("flushing left, align %a, page %a, realpage %a",align,pageno,realpageno)
end
elseif action == 2 then
- setlist(current,hpack_nodes(linked_nodes(new_stretch(3),getlist(current)),getfield(current,"width"),"exactly"))
+ local list = getlist(current)
+ local head = setlink(new_stretch(3),list) -- prepend
+ setlist(current,hpack_nodes(head,getwidth(current),"exactly"))
if trace_realign then
report_realign("flushing right. align %a, page %a, realpage %a",align,pageno,realpageno)
end
@@ -102,7 +106,6 @@ local function handler(head,leftpage,realpageno)
done = true
nofrealigned = nofrealigned + 1
end
- setattr(current,a_realign,unsetvalue)
end
end
handler(getlist(current),leftpage,realpageno)
diff --git a/tex/context/base/mkiv/spac-chr.lua b/tex/context/base/mkiv/spac-chr.lua
index 2ea53b89e..fe402ed87 100644
--- a/tex/context/base/mkiv/spac-chr.lua
+++ b/tex/context/base/mkiv/spac-chr.lua
@@ -36,6 +36,7 @@ local getnext = nuts.getnext
local getprev = nuts.getprev
local getattr = nuts.getattr
local setattr = nuts.setattr
+local setattrlist = nuts.setattrlist
local getfont = nuts.getfont
local getchar = nuts.getchar
local setsubtype = nuts.setsubtype
@@ -86,36 +87,33 @@ local c_zero = byte('0')
local c_period = byte('.')
local function inject_quad_space(unicode,head,current,fraction)
- local attr = getfield(current,"attr")
if fraction ~= 0 then
fraction = fraction * fontquads[getfont(current)]
end
local glue = new_glue(fraction)
- setfield(glue,"attr",attr)
- setfield(current,"attr",nil)
+ setattrlist(glue,current)
+ setattrlist(current) -- why reset all
setattr(glue,a_character,unicode)
head, current = insert_node_after(head,current,glue)
return head, current
end
local function inject_char_space(unicode,head,current,parent)
- local attr = getfield(current,"attr")
local font = getfont(current)
local char = fontcharacters[font][parent]
local glue = new_glue(char and char.width or fontparameters[font].space)
- setfield(glue,"attr",attr)
- setfield(current,"attr",nil)
+ setattrlist(glue,current)
+ setattrlist(current) -- why reset all
setattr(glue,a_character,unicode)
head, current = insert_node_after(head,current,glue)
return head, current
end
local function inject_nobreak_space(unicode,head,current,space,spacestretch,spaceshrink)
- local attr = getfield(current,"attr")
local glue = new_glue(space,spacestretch,spaceshrink)
local penalty = new_penalty(10000)
- setfield(glue,"attr",attr)
- setfield(current,"attr",nil)
+ setattrlist(glue,current)
+ setattrlist(current) -- why reset all
setattr(glue,a_character,unicode) -- bombs
head, current = insert_node_after(head,current,penalty)
if trace_nbsp then
diff --git a/tex/context/base/mkiv/spac-prf.lua b/tex/context/base/mkiv/spac-prf.lua
index f89d836d8..841e5d271 100644
--- a/tex/context/base/mkiv/spac-prf.lua
+++ b/tex/context/base/mkiv/spac-prf.lua
@@ -51,12 +51,22 @@ local getsubtype = nuts.getsubtype
local getlist = nuts.getlist
local gettexbox = nuts.getbox
local getwhd = nuts.getwhd
+local getglue = nuts.getglue
+local getkern = nuts.getkern
+local getshift = nuts.getshift
+local getwidth = nuts.getwidth
+local getheight = nuts.getheight
+local getdepth = nuts.getdepth
local setfield = nuts.setfield
local setlink = nuts.setlink
local setlist = nuts.setlist
local setattr = nuts.setattr
local setwhd = nuts.setwhd
+local setshift = nuts.setshift
+local setwidth = nuts.setwidth
+local setheight = nuts.setheight
+local setdepth = nuts.setdepth
local properties = nodes.properties.data
local setprop = nuts.setprop
@@ -86,6 +96,8 @@ local v_strict = variables.strict
local setcolor = nodes.tracers.colors.set
local settransparency = nodes.tracers.transparencies.set
+local enableaction = nodes.tasks.enableaction
+
local profiling = { }
builders.profiling = profiling
@@ -117,7 +129,7 @@ local function getprofile(line,step)
local step = step or 65536 -- * 2 -- 2pt
local margin = step / 4
local min = 0
- local max = ceiling(getfield(line,"width")/step) + 1
+ local max = ceiling(getwidth(line)/step) + 1
for i=min,max do
heights[i] = 0
@@ -166,7 +178,7 @@ local function getprofile(line,step)
wd, ht, dp = getwhd(current)
progress()
elseif id == kern_code then
- wd = getfield(current,"kern")
+ wd = getkern(current)
ht = 0
dp = 0
progress()
@@ -176,20 +188,26 @@ local function getprofile(line,step)
process(replace)
end
elseif id == glue_code then
- wd = getfield(current,"width")
+ local width, stretch, shrink, stretch_order, shrink_order = getglue(current)
if glue_sign == 1 then
- if getfield(current,"stretch_order") == glue_order then
- wd = wd + getfield(current,"stretch") * glue_set
+ if stretch_order == glue_order then
+ wd = width + stretch * glue_set
+ else
+ wd = width
end
elseif glue_sign == 2 then
- if getfield(current,"shrink_order") == glue_order then
- wd = wd - getfield(current,"shrink") * glue_set
+ if shrink_order == glue_order then
+ wd = width - shrink * glue_set
+ else
+ wd = width
end
+ else
+ wd = width
end
if getsubtype(current) >= leaders_code then
local leader = getleader(current)
- ht = getfield(leader,"height")
- dp = getfield(leader,"depth")
+ local w
+ w, ht, dp = getwhd(leader) -- can become getwhd(current) after 1.003
else
ht = 0
dp = 0
@@ -197,7 +215,7 @@ local function getprofile(line,step)
progress()
elseif id == hlist_code then
-- we could do a nested check .. but then we need to push / pop glue
- local shift = getfield(current,"shift")
+ local shift = getshift(current)
local w, h, d = getwhd(current)
-- if getattr(current,a_specialcontent) then
if getprop(current,"specialcontent") then
@@ -212,19 +230,19 @@ local function getprofile(line,step)
end
progress()
elseif id == vlist_code or id == unset_code then
- local shift = getfield(current,"shift") -- todo
+ local shift = getshift(current) -- todo
wd, ht, dp = getwhd(current)
progress()
elseif id == rule_code then
wd, ht, dp = getwhd(current)
progress()
elseif id == math_code then
- wd = getfield(current,"surround") + getfield(current,"width")
+ wd = getkern(current) + getwidth(current) -- surround
ht = 0
dp = 0
progress()
elseif id == marginkern_code then
- wd = getfield(current,"width")
+ wd = getwidth(current)
ht = 0
dp = 0
progress()
@@ -293,16 +311,14 @@ local function addstring(height,depth)
local dptext = depth
local httext = typesetters.tohpack(height,infofont)
local dptext = typesetters.tohpack(depth,infofont)
- setfield(httext,"shift",- 1.2 * exheight)
- setfield(dptext,"shift", 0.6 * exheight)
- local text = nuts.hpack(
- nuts.linked(
- new_kern(-getfield(httext,"width")-emwidth),
- httext,
- new_kern(-getfield(dptext,"width")),
- dptext
- )
- )
+ setshift(httext,- 1.2 * exheight)
+ setshift(dptext, 0.6 * exheight)
+ local text = hpack_nodes(setlink(
+ new_kern(-getwidth(httext)-emwidth),
+ httext,
+ new_kern(-getwidth(dptext)),
+ dptext
+ ))
setwhd(text,0,0,0)
return text
end
@@ -385,8 +401,8 @@ local function addprofile(node,profile,step)
-- if texttoo then
--
-- local text = addstring(
- -- formatters["%0.4f"](getfield(rule,"height")/65536),
- -- formatters["%0.4f"](getfield(rule,"depth") /65536)
+ -- formatters["%0.4f"](getheight(rule)/65536),
+ -- formatters["%0.4f"](getdepth(rule) /65536)
-- )
--
-- setlink(text,rule)
@@ -475,8 +491,8 @@ methods[v_strict] = function(top,bot,t_profile,b_profile,specification)
local strutdp = specification.depth or texdimen.strutdp
local lineheight = strutht + strutdp
- local depth = getfield(top,"depth")
- local height = getfield(bot,"height")
+ local depth = getdepth(top)
+ local height = getheight(bot)
local total = depth + height
local distance = specification.distance or 0
local delta = lineheight - total
@@ -511,8 +527,8 @@ methods[v_fixed] = function(top,bot,t_profile,b_profile,specification)
local strutdp = specification.depth or texdimen.strutdp
local lineheight = strutht + strutdp
- local depth = getfield(top,"depth")
- local height = getfield(bot,"height")
+ local depth = getdepth(top)
+ local height = getheight(bot)
local total = depth + height
local distance = specification.distance or 0
local delta = lineheight - total
@@ -524,8 +540,8 @@ methods[v_fixed] = function(top,bot,t_profile,b_profile,specification)
-- no distance (yet)
if delta < lineheight then
- setfield(top,"depth",strutdp)
- setfield(bot,"height",strutht)
+ setdepth(top,strutdp)
+ setheight(bot,strutht)
return true
end
@@ -536,13 +552,13 @@ methods[v_fixed] = function(top,bot,t_profile,b_profile,specification)
depth = depth - lineheight
dp = dp + lineheight
end
- setfield(top,"depth",dp)
+ setdepth(top,dp)
local ht = strutht
while height > lineheight - strutht do
height = height - lineheight
ht = ht + lineheight
end
- setfield(bot,"height",ht)
+ setheight(bot,ht)
local lines = floor(delta/lineheight)
if lines > 0 then
inject(top,bot,-lines * lineheight)
@@ -553,17 +569,17 @@ methods[v_fixed] = function(top,bot,t_profile,b_profile,specification)
end
if total < lineheight then
- setfield(top,"depth",strutdp)
- setfield(bot,"height",strutht)
+ setdepth(top,strutdp)
+ setheight(bot,strutht)
return true
end
if depth < strutdp then
- setfield(top,"depth",strutdp)
+ setdepth(top,strutdp)
total = total - depth + strutdp
end
if height < strutht then
- setfield(bot,"height",strutht)
+ setheight(bot,strutht)
total = total - height + strutht
end
@@ -663,7 +679,7 @@ local function profilelist(line,mvl)
end
break
elseif id == glue_code then
- local wd = getfield(current,"width")
+ local wd = getwidth(current)
if not wd or wd == 0 then
-- go on
else
@@ -737,7 +753,7 @@ local function profilelist(line,mvl)
if top then
local subtype = getsubtype(current)
-- if subtype == lineskip_code or subtype == baselineskip_code then
- local wd = getfield(current,"width")
+ local wd = getwidth(current)
if wd > 0 then
distance = wd
lastglue = current
@@ -781,9 +797,9 @@ local enabled = false
function profiling.set(specification)
if not enabled then
- nodes.tasks.enableaction("mvlbuilders", "builders.profiling.pagehandler")
+ enableaction("mvlbuilders", "builders.profiling.pagehandler")
-- too expensive so we expect that this happens explicitly, we keep for reference:
- -- nodes.tasks.enableaction("vboxbuilders","builders.profiling.vboxhandler")
+ -- enableaction("vboxbuilders","builders.profiling.vboxhandler")
enabled = true
end
local n = #specifications + 1
@@ -842,7 +858,7 @@ function profiling.profilebox(specification)
local subtype = getsubtype(current)
if subtype == lineskip_code or subtype == baselineskip_code then
if top then
- local wd = getfield(current,"width")
+ local wd = getwidth(current)
if wd > 0 then
distance = wd
lastglue = current
diff --git a/tex/context/base/mkiv/spac-ver.lua b/tex/context/base/mkiv/spac-ver.lua
index 37f99e760..c7eec18ee 100644
--- a/tex/context/base/mkiv/spac-ver.lua
+++ b/tex/context/base/mkiv/spac-ver.lua
@@ -30,6 +30,8 @@ if not modules then modules = { } end modules ['spac-ver'] = {
-- todo: strip baselineskip around display math
+-- todo: getglue(n,false) instead of getfield
+
local next, type, tonumber = next, type, tonumber
local gmatch, concat = string.gmatch, table.concat
local ceil, floor = math.ceil, math.floor
@@ -39,8 +41,6 @@ local allocate = utilities.storage.allocate
local todimen = string.todimen
local formatters = string.formatters
-local P, C, R, S, Cc, Carg = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.Cc, lpeg.Carg
-
local nodes = nodes
local node = node
local trackers = trackers
@@ -62,7 +62,7 @@ local implement = interfaces.implement
local v_local = variables["local"]
local v_global = variables["global"]
local v_box = variables.box
-local v_page = variables.page -- reserved for future use
+----- v_page = variables.page -- reserved for future use
local v_split = variables.split
local v_min = variables.min
local v_max = variables.max
@@ -136,15 +136,23 @@ local getprop = nuts.getprop
local setprop = nuts.setprop
local getglue = nuts.getglue
local setglue = nuts.setglue
+local getkern = nuts.getkern
+local getpenalty = nuts.getpenalty
+local setshift = nuts.setshift
+local setwidth = nuts.setwidth
+local getwidth = nuts.getwidth
+local setheight = nuts.setheight
+local getheight = nuts.getheight
+local setdepth = nuts.setdepth
+local getdepth = nuts.getdepth
local find_node_tail = nuts.tail
local flush_node = nuts.flush_node
local traverse_nodes = nuts.traverse
local traverse_nodes_id = nuts.traverse_id
local insert_node_before = nuts.insert_before
-local insert_node_after = nuts.insert_after
local remove_node = nuts.remove
-local count_nodes = nuts.count
+local count_nodes = nuts.countall
local hpack_node = nuts.hpack
local vpack_node = nuts.vpack
----- writable_spec = nuts.writable_spec
@@ -266,17 +274,6 @@ function vspacing.definesnapmethod(name,method)
context(n)
end
--- local rule_id = nodecodes.rule
--- local vlist_id = nodecodes.vlist
--- function nodes.makevtop(n)
--- if getid(n) == vlist_id then
--- local list = getlist(n)
--- local height = (list and getid(list) <= rule_id and getfield(list,"height")) or 0
--- setfield(n,"depth",getfield(n,"depth") - height + getfield(n,"height")
--- setfield(n,"height",height
--- end
--- end
-
local function validvbox(parentid,list)
if parentid == hlist_code then
local id = getid(list)
@@ -326,16 +323,16 @@ local function already_done(parentid,list,a_snapmethod) -- todo: done when only
for n in traverse_nodes(list) do
local id = getid(n)
if id == hlist_code or id == vlist_code then
--- local a = getattr(n,a_snapmethod)
--- if not a then
--- -- return true -- not snapped at all
--- elseif a == 0 then
--- return true -- already snapped
--- end
-local p = getprop(n,"snapper")
-if p then
- return p
-end
+ -- local a = getattr(n,a_snapmethod)
+ -- if not a then
+ -- -- return true -- not snapped at all
+ -- elseif a == 0 then
+ -- return true -- already snapped
+ -- end
+ local p = getprop(n,"snapper")
+ if p then
+ return p
+ end
elseif id == glue_code or id == penalty_code then -- or id == kern_code then
-- go on
else
@@ -517,7 +514,7 @@ local function snap_hlist(where,current,method,height,depth) -- method[v_strut]
ch, cd = lh, delta + d
h, d = ch, cd
local shifted = hpack_node(getlist(current))
- setfield(shifted,"shift",delta)
+ setshift(shifted,delta)
setlist(current,shifted)
done = true
if t then
@@ -552,7 +549,7 @@ local function snap_hlist(where,current,method,height,depth) -- method[v_strut]
cd, ch = ld, delta + h
h, d = ch, cd
local shifted = hpack_node(getlist(current))
- setfield(shifted,"shift",delta)
+ setshift(shifted,delta)
setlist(current,shifted)
done = true
if t then
@@ -618,7 +615,7 @@ local function snap_hlist(where,current,method,height,depth) -- method[v_strut]
t[#t+1] = formatters["before offset: %p (width %p height %p depth %p)"](offset,wd,ht,dp)
end
local shifted = hpack_node(getlist(current))
- setfield(shifted,"shift",offset)
+ setshift(shifted,offset)
setlist(current,shifted)
if t then
local wd, ht, dp = getwhd(current)
@@ -628,13 +625,13 @@ local function snap_hlist(where,current,method,height,depth) -- method[v_strut]
setattr(current,a_snapmethod,0)
end
if not height then
- setfield(current,"height",ch)
+ setheight(current,ch)
if t then
t[#t+1] = formatters["forced height: %p"](ch)
end
end
if not depth then
- setfield(current,"depth",cd)
+ setdepth(current,cd)
if t then
t[#t+1] = formatters["forced depth: %p"](cd)
end
@@ -664,8 +661,8 @@ local function snap_hlist(where,current,method,height,depth) -- method[v_strut]
end
local function snap_topskip(current,method)
- local w = getfield(current,"width") or 0
- setfield(current,"width",0)
+ local w = getwidth(current)
+ setwidth(current,0)
return w, 0
end
@@ -714,6 +711,8 @@ storage.register("builders/vspacing/data/skip", vspacingdata.skip, "builders.vsp
do -- todo: interface.variables and properties
+ local P, C, R, S, Cc = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.Cc
+
vspacing.fixed = false
local map = vspacingdata.map
@@ -834,11 +833,11 @@ local function nodes_to_string(head)
local id = getid(current)
local ty = nodecodes[id]
if id == penalty_code then
- t[#t+1] = formatters["%s:%s"](ty,getfield(current,"penalty"))
+ t[#t+1] = formatters["%s:%s"](ty,getpenalty(current))
elseif id == glue_code then
- t[#t+1] = formatters["%s:%s:%p"](ty,skipcodes[getsubtype(current)],getfield(current,"width"))
+ t[#t+1] = formatters["%s:%s:%p"](ty,skipcodes[getsubtype(current)],getwidth(current))
elseif id == kern_code then
- t[#t+1] = formatters["%s:%p"](ty,getfield(current,"kern"))
+ t[#t+1] = formatters["%s:%p"](ty,getkern(current))
else
t[#t+1] = ty
end
@@ -852,12 +851,12 @@ local function reset_tracing(head)
end
local function trace_skip(str,sc,so,sp,data)
- trace_list[#trace_list+1] = { "skip", formatters["%s | %p | category %s | order %s | penalty %s"](str, getfield(data,"width"), sc or "-", so or "-", sp or "-") }
+ trace_list[#trace_list+1] = { "skip", formatters["%s | %p | category %s | order %s | penalty %s"](str, getwidth(data), sc or "-", so or "-", sp or "-") }
tracing_info = true
end
local function trace_natural(str,data)
- trace_list[#trace_list+1] = { "skip", formatters["%s | %p"](str, getfield(data,"width")) }
+ trace_list[#trace_list+1] = { "skip", formatters["%s | %p"](str, getwidth(data)) }
tracing_info = true
end
@@ -877,9 +876,9 @@ end
local function trace_done(str,data)
if getid(data) == penalty_code then
- trace_list[#trace_list+1] = { "penalty", formatters["%s | %s"](str,getfield(data,"penalty")) }
+ trace_list[#trace_list+1] = { "penalty", formatters["%s | %s"](str,getpenalty(data)) }
else
- trace_list[#trace_list+1] = { "glue", formatters["%s | %p"](str,getfield(data,"width")) }
+ trace_list[#trace_list+1] = { "glue", formatters["%s | %p"](str,getwidth(data)) }
end
tracing_info = true
end
@@ -958,10 +957,10 @@ end
local w, h, d = 0, 0, 0
----- w, h, d = 100*65536, 65536, 65536
-local function forced_skip(head,current,width,where,trace)
+local function forced_skip(head,current,width,where,trace) -- looks old ... we have other tricks now
if head == current then
if getsubtype(head) == baselineskip_code then
- width = width - (getfield(head,"width") or 0)
+ width = width - getwidth(head)
end
end
if width == 0 then
@@ -1057,7 +1056,7 @@ specialmethods[1] = function(pagehead,pagetail,start,penalty)
report_specials(" context penalty %a, higher level, continue",p)
end
else
- local p = getfield(current,"penalty")
+ local p = getpenalty(current)
if p < 10000 then
-- assume some other mechanism kicks in so we seem to have content
if trace_specials then
@@ -1101,15 +1100,15 @@ local function check_experimental_overlay(head,current)
local skips = 0
--
-- We deal with this at the tex end .. we don't see spacing .. enabling this code
- -- is probably harmless btu then we need to test it.
+ -- is probably harmless but then we need to test it.
--
local c = getnext(p)
while c and c ~= n do
local id = getid(c)
if id == glue_code then
- skips = skips + (getfield(c,"width") or 0)
+ skips = skips + getwidth(c)
elseif id == kern_code then
- skips = skips + getfield(c,"kern")
+ skips = skips + getkern(c)
end
c = getnext(c)
end
@@ -1119,7 +1118,7 @@ local function check_experimental_overlay(head,current)
local k = new_kern(-delta)
if n_ht > p_ht then
-- we should adapt pagetotal ! (need a hook for that) .. now we have the wrong pagebreak
- setfield(p,"height",n_ht)
+ setheight(p,n_ht)
end
insert_node_before(head,n,k)
if p == head then
@@ -1230,18 +1229,18 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also
local function compensate(n)
local g = 0
while n and getid(n) == glue_code do
- g = g + getfield(n,"width")
+ g = g + getwidth(n)
n = getnext(n)
end
if n then
local p = getprop(n,"snapper")
if p then
local extra = p.extra
- if extra < 0 then
- local h = p.ch -- getfield(n,"height")
+ if extra and extra < 0 then -- hm, extra can be unset ... needs checking
+ local h = p.ch -- getheight(n)
-- maybe an extra check
-- if h - extra < g then
- setfield(n,"height",h-2*extra)
+ setheight(n,h-2*extra)
p.extra = 0
if trace_vsnapping then
report_snapper("removed extra space at top: %p",extra)
@@ -1326,16 +1325,16 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also
if trace then
trace_done("flushed due to forced " .. why,glue_data)
end
- head = forced_skip(head,current,getfield(glue_data,"width") or 0,"before",trace)
+ head = forced_skip(head,current,getwidth(glue_data,width),"before",trace)
flush_node(glue_data)
else
- local w = getfield(glue_data,"width")
- if w ~= 0 then
+ local width, stretch, shrink = getglue(glue_data)
+ if width ~= 0 then
if trace then
trace_done("flushed due to non zero " .. why,glue_data)
end
head = insert_node_before(head,current,glue_data)
- elseif getfield(glue_data,"stretch") ~= 0 or getfield(glue_data,"shrink") ~= 0 then
+ elseif stretch ~= 0 or shrink ~= 0 then
if trace then
trace_done("flushed due to stretch/shrink in" .. why,glue_data)
end
@@ -1398,16 +1397,15 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also
end
else
local h, d, ch, cd, lines, extra = snap_hlist("mvl",current,sv,false,false)
-lastsnap = {
- ht = h,
- dp = d,
- ch = ch,
- cd = cd,
- extra = extra,
- current = current,
-}
-setprop(current,"snapper",lastsnap)
-
+ lastsnap = {
+ ht = h,
+ dp = d,
+ ch = ch,
+ cd = cd,
+ extra = extra,
+ current = current,
+ }
+ setprop(current,"snapper",lastsnap)
if trace_vsnapping then
report_snapper("mvl %a snapped from (%p,%p) to (%p,%p) using method %a (%s) for %a (%s lines): %s",
nodecodes[id],h,d,ch,cd,sv.name,sv.specification,where,lines,listtoutf(list))
@@ -1425,15 +1423,15 @@ setprop(current,"snapper",lastsnap)
flush("list")
current = getnext(current)
elseif id == penalty_code then
- -- natural_penalty = getfield(current,"penalty")
+ -- natural_penalty = getpenalty(current)
-- if trace then
-- trace_done("removed penalty",current)
-- end
-- head, current = remove_node(head, current, true)
current = getnext(current)
elseif id == kern_code then
- if snap and trace_vsnapping and getfield(current,"kern") ~= 0 then
- report_snapper("kern of %p kept",getfield(current,"kern"))
+ if snap and trace_vsnapping and getkern(current) ~= 0 then
+ report_snapper("kern of %p kept",getkern(current))
end
flush("kern")
current = getnext(current)
@@ -1572,8 +1570,8 @@ setprop(current,"snapper",lastsnap)
elseif glue_order == so then
-- is now exclusive, maybe support goback as combi, else why a set
if sc == largest then
- local cw = getfield(current,"width") or 0
- local gw = getfield(glue_data,"width") or 0
+ local cw = getwidth(current)
+ local gw = getwidth(glue_data)
if cw > gw then
if trace then
trace_skip("largest",sc,so,sp,current)
@@ -1636,7 +1634,7 @@ setprop(current,"snapper",lastsnap)
local s = getattr(current,a_snapmethod)
if s and s ~= 0 then
setattr(current,a_snapmethod,0)
- setfield(current,"width",0)
+ setwidth(current,0)
if trace_vsnapping then
report_snapper("lineskip set to zero")
end
@@ -1658,7 +1656,7 @@ setprop(current,"snapper",lastsnap)
local s = getattr(current,a_snapmethod)
if s and s ~= 0 then
setattr(current,a_snapmethod,0)
- setfield(current,"width",0)
+ setwidth(current,0)
if trace_vsnapping then
report_snapper("baselineskip set to zero")
end
@@ -1683,8 +1681,8 @@ setprop(current,"snapper",lastsnap)
end
head, current = remove_node(head, current, true)
elseif glue_data then
- local w = getfield(current,"width") or 0
- if ((w ~= 0) and (w > (getfield(glue_data,"width") or 0))) then
+ local w = getwidth(current)
+ if (w ~= 0) and (w > getwidth(glue_data)) then
glue_data = current
if trace then
trace_natural("taking parskip",current)
@@ -1763,7 +1761,7 @@ setprop(current,"snapper",lastsnap)
--
else -- other glue
if snap and trace_vsnapping then
- local w = getfield(current,"width") or 0
+ local w = getwidth(current)
if w ~= 0 then
report_snapper("glue %p of type %a kept",w,skipcodes[subtype])
end
@@ -1795,7 +1793,7 @@ setprop(current,"snapper",lastsnap)
if trace then
trace_done("result",p)
end
- head, tail = insert_node_after(head,tail,p)
+ setlink(tail,p)
-- if penalty_data > special_penalty_min and penalty_data < special_penalty_max then
local props = properties[p]
if props then
@@ -1813,11 +1811,13 @@ setprop(current,"snapper",lastsnap)
trace_done("result",glue_data)
end
if force_glue then
- head, tail = forced_skip(head,tail,getfield(glue_data,"width") or 0,"after",trace)
+ head, tail = forced_skip(head,tail,getwidth(glue_data),"after",trace)
flush_node(glue_data)
glue_data = nil
+ elseif tail then
+ setlink(tail,glue_data)
else
- head, tail = insert_node_after(head,tail,glue_data)
+ head = glue_data
end
texnest[texnest.ptr].prevdepth = 0 -- appending to the list bypasses tex's prevdepth handler
end
@@ -1911,36 +1911,40 @@ function vspacing.pagehandler(newhead,where)
return nil
end
-local ignore = table.tohash {
- "split_keep",
- "split_off",
- -- "vbox",
-}
+do
-function vspacing.vboxhandler(head,where)
- if head and not ignore[where] then
- local h = tonut(head)
- if getnext(h) then -- what if a one liner and snapping?
- h = collapser(h,"vbox",where,trace_vbox_vspacing,true,a_snapvbox) -- todo: local snapper
- return tonode(h)
+ local ignore = table.tohash {
+ "split_keep",
+ "split_off",
+ -- "vbox",
+ }
+
+ function vspacing.vboxhandler(head,where)
+ if head and not ignore[where] then
+ local h = tonut(head)
+ if getnext(h) then -- what if a one liner and snapping?
+ h = collapser(h,"vbox",where,trace_vbox_vspacing,true,a_snapvbox) -- todo: local snapper
+ return tonode(h)
+ end
end
+ return head
end
- return head
-end
-function vspacing.collapsevbox(n,aslist) -- for boxes but using global a_snapmethod
- local box = getbox(n)
- if box then
- local list = getlist(box)
- if list then
- list = collapser(list,"snapper","vbox",trace_vbox_vspacing,true,a_snapmethod)
- if aslist then
- setlist(box,list) -- beware, dimensions of box are wrong now
- else
- setlist(box,vpack_node(list))
+ function vspacing.collapsevbox(n,aslist) -- for boxes but using global a_snapmethod
+ local box = getbox(n)
+ if box then
+ local list = getlist(box)
+ if list then
+ list = collapser(list,"snapper","vbox",trace_vbox_vspacing,true,a_snapmethod)
+ if aslist then
+ setlist(box,list) -- beware, dimensions of box are wrong now
+ else
+ setlist(box,vpack_node(list))
+ end
end
end
end
+
end
-- This one is needed to prevent bleeding of prevdepth to the next page
@@ -1979,71 +1983,75 @@ end
-- interface
-implement {
- name = "vspacing",
- actions = vspacing.analyze,
- scope = "private",
- arguments = "string"
-}
-
-implement {
- name = "resetprevdepth",
- actions = vspacing.resetprevdepth,
- scope = "private"
-}
-
-implement {
- name = "vspacingsetamount",
- actions = vspacing.setskip,
- scope = "private",
- arguments = "string",
-}
-
-implement {
- name = "vspacingdefine",
- actions = vspacing.setmap,
- scope = "private",
- arguments = { "string", "string" }
-}
-
-implement {
- name = "vspacingcollapse",
- actions = vspacing.collapsevbox,
- scope = "private",
- arguments = "integer"
-}
-
-implement {
- name = "vspacingcollapseonly",
- actions = vspacing.collapsevbox,
- scope = "private",
- arguments = { "integer", true }
-}
-
-implement {
- name = "vspacingsnap",
- actions = vspacing.snapbox,
- scope = "private",
- arguments = { "integer", "integer" }
-}
-
-implement {
- name = "definesnapmethod",
- actions = vspacing.definesnapmethod,
- scope = "private",
- arguments = { "string", "string" }
-}
-
-local remove_node = nodes.remove
-local find_node_tail = nodes.tail
+do
-interfaces.implement {
- name = "fakenextstrutline",
- actions = function()
- local head = texlists.page_head
- if head then
- local head = remove_node(head,find_node_tail(head),true)
- texlists.page_head = head
+ implement {
+ name = "vspacing",
+ actions = vspacing.analyze,
+ scope = "private",
+ arguments = "string"
+ }
+
+ implement {
+ name = "resetprevdepth",
+ actions = vspacing.resetprevdepth,
+ scope = "private"
+ }
+
+ implement {
+ name = "vspacingsetamount",
+ actions = vspacing.setskip,
+ scope = "private",
+ arguments = "string",
+ }
+
+ implement {
+ name = "vspacingdefine",
+ actions = vspacing.setmap,
+ scope = "private",
+ arguments = { "string", "string" }
+ }
+
+ implement {
+ name = "vspacingcollapse",
+ actions = vspacing.collapsevbox,
+ scope = "private",
+ arguments = "integer"
+ }
+
+ implement {
+ name = "vspacingcollapseonly",
+ actions = vspacing.collapsevbox,
+ scope = "private",
+ arguments = { "integer", true }
+ }
+
+ implement {
+ name = "vspacingsnap",
+ actions = vspacing.snapbox,
+ scope = "private",
+ arguments = { "integer", "integer" }
+ }
+
+ implement {
+ name = "definesnapmethod",
+ actions = vspacing.definesnapmethod,
+ scope = "private",
+ arguments = { "string", "string" }
+ }
+
+ local remove_node = nodes.remove
+ local find_node_tail = nodes.tail
+
+ interfaces.implement {
+ name = "fakenextstrutline",
+ actions = function()
+ local head = texlists.page_head
+ if head then
+ local head = remove_node(head,find_node_tail(head),true)
+ texlists.page_head = head
+ end
end
- end
-}
+ }
+
+end
diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf
index ed9a82192..c01ed7449 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 c6c5939bb..d9528aa62 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-con.mkvi b/tex/context/base/mkiv/strc-con.mkvi
index 396869608..18ce17355 100644
--- a/tex/context/base/mkiv/strc-con.mkvi
+++ b/tex/context/base/mkiv/strc-con.mkvi
@@ -971,8 +971,8 @@
catcodes \catcodetable
}
references {
- internal \nextinternalreference
- order \nextinternalorderreference
+ internal \locationcount
+ order \locationorder
reference {\currentconstructionreference}
prefix {\currentconstructionreferenceprefix}
% block {\currentsectionblock}
@@ -1016,7 +1016,7 @@
\clf_setinternalreference
prefix {\referenceprefix}%
reference {\currentconstructionreference}%
- internal \nextinternalreference
+ internal \locationcount
view {\interactionparameter\c!focus}%
\relax
\normalexpanded{%
diff --git a/tex/context/base/mkiv/strc-doc.lua b/tex/context/base/mkiv/strc-doc.lua
index 105e5ad8d..57fff5a21 100644
--- a/tex/context/base/mkiv/strc-doc.lua
+++ b/tex/context/base/mkiv/strc-doc.lua
@@ -16,7 +16,7 @@ if not modules then modules = { } end modules ['strc-doc'] = {
-- in lists however zero's are ignored, so there numbersegments=2:4 gives result
local next, type, tonumber, select = next, type, tonumber, select
-local format, gsub, find, gmatch, match = string.format, string.gsub, string.find, string.gmatch, string.match
+local find, match = string.find, string.match
local concat, fastcopy, insert, remove = table.concat, table.fastcopy, table.insert, table.remove
local max, min = math.max, math.min
local allocate, mark, accesstable = utilities.storage.allocate, utilities.storage.mark, utilities.tables.accesstable
@@ -411,16 +411,17 @@ function sections.setentry(given)
v[2](k)
end
end
- local n = { }
- for i=1,newdepth do
- n[i] = numbers[i]
- end
- numberdata.numbers = n
+-- local n = { }
+-- for i=1,newdepth do
+-- n[i] = numbers[i]
+-- end
+-- numberdata.numbers = n
+ numberdata.numbers = { unpack(numbers,1,newdepth) }
if not numberdata.block then
numberdata.block = getcurrentblock() -- also in references
end
if #ownnumbers > 0 then
- numberdata.ownnumbers = fastcopy(ownnumbers)
+ numberdata.ownnumbers = fastcopy(ownnumbers) -- { unpack(ownnumbers) }
end
if trace_detail then
report_structure("name %a, numbers % a, own numbers % a",givenname,numberdata.numbers,numberdata.ownnumbers)
diff --git a/tex/context/base/mkiv/strc-doc.mkiv b/tex/context/base/mkiv/strc-doc.mkiv
index c453f199e..5f40521fa 100644
--- a/tex/context/base/mkiv/strc-doc.mkiv
+++ b/tex/context/base/mkiv/strc-doc.mkiv
@@ -23,10 +23,10 @@
{\clf_setinternalreference
prefix {\currentstructurereferenceprefix}%
reference {\currentstructurereference}
- internal \nextinternalreference
+ internal \locationcount
view {\interactionparameter\c!focus}%
\relax
\xdef\currentstructureattribute {\the\lastdestinationattribute}%
- \xdef\currentstructuresynchronize{\strc_lists_inject_enhance{#1}{\nextinternalreference}}}
+ \xdef\currentstructuresynchronize{\strc_lists_inject_enhance{#1}{\the\locationcount}}}
\protect \endinput
diff --git a/tex/context/base/mkiv/strc-enu.mkvi b/tex/context/base/mkiv/strc-enu.mkvi
index aaf735918..8eff706bb 100644
--- a/tex/context/base/mkiv/strc-enu.mkvi
+++ b/tex/context/base/mkiv/strc-enu.mkvi
@@ -366,7 +366,7 @@
\strc_enumerations_full_number_yes
\edef\p_coupling{\constructionparameter\c!coupling}%
\ifx\p_coupling\empty \else
- \symbolreference[order(construction:\p_coupling:\nextinternalorderreference)]%
+ \symbolreference[order(construction:\p_coupling:\the\locationorder)]%
\fi
\fi}
diff --git a/tex/context/base/mkiv/strc-itm.mkvi b/tex/context/base/mkiv/strc-itm.mkvi
index e622318c3..a28193415 100644
--- a/tex/context/base/mkiv/strc-itm.mkvi
+++ b/tex/context/base/mkiv/strc-itm.mkvi
@@ -274,7 +274,7 @@
catcodes \catcodetable
}%
references {%
- internal \nextinternalreference % no: this spoils references
+ internal \locationcount % no: this spoils references
% block {\currentsectionblock}%
view {\interactionparameter\c!focus}%
prefix {\referenceprefix}%
diff --git a/tex/context/base/mkiv/strc-lst.mkvi b/tex/context/base/mkiv/strc-lst.mkvi
index 4309ae93a..a3718af18 100644
--- a/tex/context/base/mkiv/strc-lst.mkvi
+++ b/tex/context/base/mkiv/strc-lst.mkvi
@@ -145,7 +145,7 @@
{\endgroup}
\unexpanded\def\strc_lists_inject_enhance#listindex#internal%
- {\normalexpanded{\ctxlatecommand{enhancelist(#listindex)}}}
+ {\normalexpanded{\ctxlatecommand{enhancelist(\number#listindex)}}}
\unexpanded\def\strc_lists_inject_yes[#settings][#userdata]% can be used directly
{\setupcurrentlist[\c!type=userdata,\c!location=\v!none,#settings]% grouped (use \let...
@@ -153,7 +153,7 @@
\setnextinternalreference
\scratchcounter\clf_addtolist
references {
- internal \nextinternalreference
+ internal \locationcount
% block {\currentsectionblock}
% section structures.sections.currentid()
% location {\p_location}
@@ -167,12 +167,12 @@
userdata {\detokenize\expandafter{\normalexpanded{#userdata}}}
\relax
\edef\currentlistnumber{\the\scratchcounter}%
-\setxvalue{\??listlocations\currentlist}{\nextinternalreference}%
+\setxvalue{\??listlocations\currentlist}{\the\locationcount}%
\ifx\p_location\v!here
% this branch injects nodes !
- \strc_lists_inject_enhance{\currentlistnumber}{\nextinternalreference}%
+ \strc_lists_inject_enhance{\currentlistnumber}{\the\locationcount}%
\clf_setinternalreference
- internal \nextinternalreference
+ internal \locationcount
view {\interactionparameter\c!focus}%
\relax % this will change
\xdef\currentstructurelistattribute{\the\lastdestinationattribute}%
diff --git a/tex/context/base/mkiv/strc-mar.lua b/tex/context/base/mkiv/strc-mar.lua
index 8b30e8514..624972af4 100644
--- a/tex/context/base/mkiv/strc-mar.lua
+++ b/tex/context/base/mkiv/strc-mar.lua
@@ -31,7 +31,8 @@ local getlist = nuts.getlist
local getattr = nuts.getattr
local getbox = nuts.getbox
-local traverse_nodes = nuts.traverse
+local traverse = nuts.traverse
+local traverse_id = nuts.traverse_id
local nodecodes = nodes.nodecodes
local glyph_code = nodecodes.glyph
@@ -117,7 +118,7 @@ end
-- identify range
local function sweep(head,first,last)
- for n in traverse_nodes(head) do
+ for n in traverse(head) do
local id = getid(n)
if id == glyph_code then
local a = getattr(n,a_marks)
diff --git a/tex/context/base/mkiv/strc-mat.mkiv b/tex/context/base/mkiv/strc-mat.mkiv
index 4c6b88c8a..4308666f3 100644
--- a/tex/context/base/mkiv/strc-mat.mkiv
+++ b/tex/context/base/mkiv/strc-mat.mkiv
@@ -518,8 +518,6 @@
%D Tricky stuff:
-\newdimen\lastlinewidth
-
\abovedisplayskip \zeropoint
\abovedisplayshortskip \zeropoint % evt. 0pt minus 3pt
\belowdisplayskip \zeropoint
@@ -529,6 +527,8 @@
\postdisplaypenalty \zerocount % -5000 goes wrong, see penalty at \section
\mathdisplayskipmode \plusthree % because align also adds
+% \predisplaygapfactor \zerocount % default is 2000
+
\unexpanded\def\strc_formulas_forget_display_skips
{\mathdisplayskipmode \plusthree
\abovedisplayskip \zeropoint
diff --git a/tex/context/base/mkiv/strc-not.lua b/tex/context/base/mkiv/strc-not.lua
index c54cd442e..1464c7f73 100644
--- a/tex/context/base/mkiv/strc-not.lua
+++ b/tex/context/base/mkiv/strc-not.lua
@@ -26,8 +26,11 @@ local counterspecials = counters.specials
local texgetcount = tex.getcount
local texgetbox = tex.getbox
+-- todo: allocate
+
notes.states = notes.states or { }
lists.enhancers = lists.enhancers or { }
+notes.numbers = notes.numbers or { }
storage.register("structures/notes/states", notes.states, "structures.notes.states")
@@ -143,6 +146,8 @@ end
notes.setstate = setstate
notes.getstate = getstate
+
+
implement {
name = "setnotestate",
actions = setstate,
@@ -157,6 +162,7 @@ implement {
function notes.define(tag,kind,number)
local state = setstate(tag,kind)
+ notes.numbers[number] = state
state.number = number
end
@@ -451,23 +457,39 @@ end
-- for the moment here but better in some builder modules
+-- gets register "n" and location "i" (where 1 is before)
+
+-- this is an experiment, we will make a more general handler instead
+-- of the current note one
+
local report_insert = logs.reporter("pagebuilder","insert")
local trace_insert = false trackers.register("pagebuilder.insert",function(v) trace_insert = v end)
local texgetglue = tex.getglue
------ texsetglue = tex.setglue
+local texsetglue = tex.setglue
-function notes.check_spacing(n,i)
+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 gi, pi, mi = 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)
report_insert("%s %i: %p plus %p minus %p","effective",n,gt,pt,mt)
end
- -- texsetglue(0,gt,pt,mt) -- for the moment we use skip register 0
return gt, pt, mt
end
-callback.register("build_page_insert", notes.check_spacing)
+notes.check_spacing = check_spacing
+
+callback.register("build_page_insert", function(n,i)
+ local state = notes.numbers[n]
+ if state then
+ -- only notes, kind of hardcoded .. bah
+ local gt, pt, mt = check_spacing(n,i)
+ texsetglue(0,gt,pt,mt) -- for the moment we use skip register 0
+ return 0
+ else
+ return n
+ end
+end)
diff --git a/tex/context/base/mkiv/strc-not.mkvi b/tex/context/base/mkiv/strc-not.mkvi
index d2626d2ab..f1a51c5ad 100644
--- a/tex/context/base/mkiv/strc-not.mkvi
+++ b/tex/context/base/mkiv/strc-not.mkvi
@@ -404,7 +404,11 @@
\setexpandednoteparameter\s!insert{\namednoteparameter\currentnoteparent\s!insert}%
\definenotation[\currentnote][\currentnoteparent][\c!type=\v!note]%
\fi
- \clf_definenote{\currentnote}{insert}\currentnoteinsertionnumber\relax
+ \clf_definenote
+ {\currentnote}%
+ {insert}%
+ \currentnoteinsertionnumber
+ \relax
\to \everydefinenote
% maybe we will share this at some point:
diff --git a/tex/context/base/mkiv/strc-num.mkiv b/tex/context/base/mkiv/strc-num.mkiv
index 2418130f9..4b222801a 100644
--- a/tex/context/base/mkiv/strc-num.mkiv
+++ b/tex/context/base/mkiv/strc-num.mkiv
@@ -545,7 +545,7 @@
\clf_setdestinationattribute
{%
references {%
- internal \nextinternalreference
+ internal \locationcount
% block {\currentsectionblock}% move to lua
view {\interactionparameter\c!focus}%
prefix {\currentstructurecomponentreferenceprefix}%
@@ -621,7 +621,7 @@
\fi
}
references {
- internal \nextinternalreference
+ internal \locationcount
% block {\currentsectionblock}
reference {\currentstructurecomponentreference}
prefix {\currentstructurecomponentreferenceprefix}
@@ -670,10 +670,10 @@
\relax
\xdef\m_strc_counters_last_registered_index{\the\scratchcounter}%
\clf_setinternalreference
- internal \nextinternalreference
+ internal \locationcount
\relax
\xdef\m_strc_counters_last_registered_attribute {\the\lastdestinationattribute}%
- \xdef\m_strc_counters_last_registered_synchronize{\strc_lists_inject_enhance{\m_strc_counters_last_registered_index}{\nextinternalreference}}}
+ \xdef\m_strc_counters_last_registered_synchronize{\strc_lists_inject_enhance{\m_strc_counters_last_registered_index}{\the\locationcount}}}
\let\m_strc_counters_last_registered_index \relax
\let\m_strc_counters_last_registered_attribute \relax
diff --git a/tex/context/base/mkiv/strc-ref.mkvi b/tex/context/base/mkiv/strc-ref.mkvi
index 96cb61b4a..9f2a7b91c 100644
--- a/tex/context/base/mkiv/strc-ref.mkvi
+++ b/tex/context/base/mkiv/strc-ref.mkvi
@@ -219,7 +219,7 @@
\clf_setdestinationattribute
{%
references {%
- internal \nextinternalreference
+ internal \locationcount
% block {\currentsectionblock}%
view {\interactionparameter\c!focus}%
\ifx\referenceprefix\empty\else
@@ -281,7 +281,7 @@
\clf_setdestinationattribute
{%
references {%
- internal \nextinternalreference
+ internal \locationcount
% block {\currentsectionblock}%
view {\interactionparameter\c!focus}%
\ifx\referenceprefix\empty\else
@@ -310,7 +310,7 @@
\clf_setdestinationattribute
{%
references {%
- internal \nextinternalreference
+ internal \locationcount
% block {\currentsectionblock}%
view {\interactionparameter\c!focus}%
\ifx\referenceprefix\empty\else
@@ -401,7 +401,7 @@
prefix {\referenceprefix}%
\fi
reference {#label}%
- internal \nextinternalreference
+ internal \locationcount
}%
metadata {%
kind {\s!page}%
@@ -424,7 +424,7 @@
references {%
view {\interactionparameter\c!focus}%
reference {#label}%
- internal \nextinternalreference
+ internal \locationcount
}%
metadata {%
kind {\s!page}%
@@ -847,7 +847,7 @@
\letvalue{\??savedinternalreference\s!default}\!!zerocount
\unexpanded\def\storeinternalreference#1#2%
- {\setxvalue{\??savedinternalreference\currentstructurename}{#2}}
+ {\setxvalue{\??savedinternalreference\currentstructurename}{\number#2}}
\newconditional\preferpagereferences
diff --git a/tex/context/base/mkiv/strc-reg.mkiv b/tex/context/base/mkiv/strc-reg.mkiv
index 5b32c6fc8..380cc9f22 100644
--- a/tex/context/base/mkiv/strc-reg.mkiv
+++ b/tex/context/base/mkiv/strc-reg.mkiv
@@ -298,7 +298,7 @@
userdata {\detokenize\expandafter{\normalexpanded{#3}}}
}%
\clf_setinternalreference
- internal \nextinternalreference
+ internal \locationcount
view {\interactionparameter\c!focus}%
\relax % this will change
\ifx\currentregisterownnumber\v!yes
@@ -337,7 +337,7 @@
}%
% overlap with the above
% \clf_setinternalreference
- % internal \nextinternalreference
+ % internal \locationcount
% view {\interactionparameter\c!focus}%
\relax % this will change
\xdef\currentregistersynchronize{\ctxlatecommand{enhanceregister("\currentregister",\currentregisternumber)}}%
@@ -524,7 +524,7 @@
}%
}}%
\clf_setinternalreference
- internal \nextinternalreference
+ internal \locationcount
view {\interactionparameter\c!focus}%
\relax % this will change
\dostarttagged\t!registerlocation\currentregister
diff --git a/tex/context/base/mkiv/strc-ren.mkiv b/tex/context/base/mkiv/strc-ren.mkiv
index b5fc9e11d..b3b9f04d9 100644
--- a/tex/context/base/mkiv/strc-ren.mkiv
+++ b/tex/context/base/mkiv/strc-ren.mkiv
@@ -82,24 +82,24 @@
\def\headreferenceattributes
{\iflocation
- % \ctxlua{structures.lists.taglocation(\nextinternalreference)}% maybe ... tags entry as used
+ % \ctxlua{structures.lists.taglocation(\the\locationcount)}% maybe ... tags entry as used
attr \destinationattribute \currentstructureattribute
attr \referenceattribute \currentstructurereferenceattribute
- % attr \internalattribute \nextinternalreference
+ % attr \internalattribute \locationcount
\fi}
\def\setinlineheadreferenceattributes
{\ifconditional\headisdisplay \else \iflocation
\attribute\destinationattribute\currentstructureattribute
\attribute\referenceattribute \currentstructurereferenceattribute
- % \attribute\internalattribute \nextinternalreference
+ % \attribute\internalattribute \locationcount
\fi \fi}
\def\docheckheadreference
{\edef\currentheadinteraction{\headparameter\c!interaction}%
\ifx\currentheadinteraction\v!list
% setuphead[<section>][interaction=list,...]
- \strc_references_get_simple_reference{*\nextinternalreference}%
+ \strc_references_get_simple_reference{*\the\locationcount}%
\let\currentstructurereferenceattribute\currentreferenceattribute
\else\ifx\currentheadinteraction\v!reference
% setuphead[<section>][interaction=reference,...] start<section>[backreference=abc,...]
diff --git a/tex/context/base/mkiv/strc-sec.mkiv b/tex/context/base/mkiv/strc-sec.mkiv
index 51b464eb9..b0771b475 100644
--- a/tex/context/base/mkiv/strc-sec.mkiv
+++ b/tex/context/base/mkiv/strc-sec.mkiv
@@ -176,11 +176,11 @@
\globallet\currentstructurecoding\s!tex
\fi
\setnextinternalreference
- \storeinternalreference\currentstructurename\nextinternalreference %
+ \storeinternalreference\currentstructurename{\the\locationcount}%
\strc_sectioning_set_reference_prefix
\clf_setsectionentry
references {
- internal \nextinternalreference\space
+ internal \locationcount
% block {\currentsectionblock}
prefix {\currentstructurereferenceprefix}
reference {\currentstructurereference}
@@ -225,7 +225,7 @@
numberdata {
% block {\currentsectionblock}
\ifx\currentstructureshownumber\v!no
- hidenumber \space true\space
+ hidenumber \space true\space % space needed for parser
\fi
separatorset {\structureparameter\c!sectionseparatorset}
conversionset {\structureparameter\c!sectionconversionset}
@@ -445,7 +445,7 @@
\clf_registersection {\currenthead} {
coupling {\currentsectionheadcoupling}
section {\currentsectionheadsection}
- level \currentsectionlevel
+ level \space \currentsectionlevel \space % space needed for parser
parent {\currentheadparent}
}%
\endgroup
diff --git a/tex/context/base/mkiv/supp-box.lua b/tex/context/base/mkiv/supp-box.lua
index 4e28f2805..b9bf0ccf0 100644
--- a/tex/context/base/mkiv/supp-box.lua
+++ b/tex/context/base/mkiv/supp-box.lua
@@ -38,6 +38,8 @@ local getid = nuts.getid
local getlist = nuts.getlist
local getattribute = nuts.getattribute
local getbox = nuts.getbox
+local getdir = nuts.getdir
+local getwidth = nuts.getwidth
local takebox = nuts.takebox
local setfield = nuts.setfield
@@ -46,6 +48,10 @@ local setboth = nuts.setboth
local setnext = nuts.setnext
local setbox = nuts.setbox
local setlist = nuts.setlist
+local setdisc = nuts.setdisc
+local setwidth = nuts.setwidth
+local setheight = nuts.setheight
+local setdepth = nuts.setdepth
local flush_node = nuts.flush_node
local flush_list = nuts.flush_list
@@ -53,7 +59,6 @@ local copy_node = nuts.copy
local copy_list = nuts.copy_list
local find_tail = nuts.tail
local traverse_id = nuts.traverse_id
-local link_nodes = nuts.linked
local list_dimensions = nuts.dimensions
local hpack = nuts.hpack
@@ -78,12 +83,6 @@ local function hyphenatedlist(head,usecolor)
local prev = getprev(current)
if id == disc_code then
local pre, post, replace = getdisc(current)
- if pre then
- setfield(current,"pre",nil)
- end
- if post then
- setfield(current,"post",nil)
- end
if not usecolor then
-- nothing fancy done
elseif pre and post then
@@ -96,23 +95,32 @@ local function hyphenatedlist(head,usecolor)
end
if replace then
flush_list(replace)
- setfield(current,"replace",nil)
end
+ setdisc(current)
setboth(current)
- local list = link_nodes (
+-- local list = setlink (
+-- pre and new_penalty(10000),
+-- pre,
+-- current,
+-- post,
+-- post and new_penalty(10000)
+-- )
+-- local tail = find_tail(list)
+-- if prev then
+-- setlink(prev,list)
+-- end
+-- if next then
+-- setlink(tail,next)
+-- end
+ setlink (
+ prev, -- there had better be one
pre and new_penalty(10000),
pre,
current,
post,
- post and new_penalty(10000)
+ post and new_penalty(10000),
+ next
)
- local tail = find_tail(list)
- if prev then
- setlink(prev,list)
- end
- if next then
- setlink(tail,next)
- end
-- flush_node(current)
elseif id == vlist_code or id == hlist_code then
hyphenatedlist(getlist(current))
@@ -351,8 +359,8 @@ implement {
actions = function(n)
local b = getbox(n)
local factor = texget("baselineskip",false) / texget("hsize")
- setfield(b,"depth",0)
- setfield(b,"height",getfield(b,"width") * factor)
+ setdepth(b,0)
+ setheight(b,getwidth(b) * factor)
end
}
@@ -426,7 +434,7 @@ local function firstdirinbox(n)
local l = getlist(b)
if l then
for h in traverse_id(hlist_code,l) do
- return getfield(h,"dir")
+ return getdir(h)
end
end
end
@@ -552,48 +560,57 @@ do
end
end
- interfaces.implement {
+ implement {
name = "putboxincache",
arguments = { "string", "string", "integer" },
actions = boxes.save,
}
- interfaces.implement {
+ implement {
name = "getboxfromcache",
arguments = { "string", "string", "integer" },
actions = boxes.restore,
}
- interfaces.implement {
+ implement {
name = "directboxfromcache",
arguments = { "string", "string" },
actions = { boxes.direct, context },
-- actions = function(category,name) local b = boxes.direct(category,name) if b then context(b) end end,
}
- interfaces.implement {
+ implement {
name = "directcopyboxfromcache",
arguments = { "string", "string", true },
actions = { boxes.direct, context },
-- actions = function(category,name) local b = boxes.direct(category,name,true) if b then context(b) end end,
}
- interfaces.implement {
+ implement {
name = "copyboxfromcache",
arguments = { "string", "string", "integer", true },
actions = boxes.restore,
}
- interfaces.implement {
+ implement {
name = "doifelseboxincache",
arguments = { "string", "string" },
actions = { boxes.found, doifelse },
}
- interfaces.implement {
+ implement {
name = "resetboxesincache",
arguments = { "string" },
actions = boxes.reset,
}
+ implement {
+ name = "lastlinewidth",
+ actions = function()
+ local head = tex.lists.page_head
+ -- list dimensions returns 3 value but we take the first
+ context(head and list_dimensions(getlist(find_tail(tonut(tex.lists.page_head)))) or 0)
+ end
+ }
+
end
diff --git a/tex/context/base/mkiv/supp-box.mkiv b/tex/context/base/mkiv/supp-box.mkiv
index 8e38c4afa..9d2817cee 100644
--- a/tex/context/base/mkiv/supp-box.mkiv
+++ b/tex/context/base/mkiv/supp-box.mkiv
@@ -2971,6 +2971,10 @@
{\expandafter\newbox\csname\??localbox\string#1\endcsname
\newlocalbox#1}
+%D Who knows when this comes in handy:
+
+\unexpanded\def\lastlinewidth{\dimexpr\clf_lastlinelength\scaledpoint\relax}
+
\protect \endinput
% a bit of test code:
diff --git a/tex/context/base/mkiv/syst-aux.mkiv b/tex/context/base/mkiv/syst-aux.mkiv
index bff1b8428..eb5b3b90a 100644
--- a/tex/context/base/mkiv/syst-aux.mkiv
+++ b/tex/context/base/mkiv/syst-aux.mkiv
@@ -7021,7 +7021,7 @@
\unexpanded\def\retestfeature % timer support is new per 10/5/2005
{\bgroup
\ifcase\interactionmode\let\wait\relax\fi
- \writestatus\m!system{starting feature test}\wait
+ \writestatus\m!system{starting feature test (n=\number\c_syst_helpers_test_feature_m)}\wait
\resettimer
\c_syst_helpers_test_feature_n\zerocount
\syst_helpers_test_feature_step
diff --git a/tex/context/base/mkiv/tabl-xtb.lua b/tex/context/base/mkiv/tabl-xtb.lua
index 62c95cbe6..dade345fc 100644
--- a/tex/context/base/mkiv/tabl-xtb.lua
+++ b/tex/context/base/mkiv/tabl-xtb.lua
@@ -71,6 +71,8 @@ local getwhd = nuts.getwhd
local setfield = nuts.setfield
local setlink = nuts.setlink
+local setdir = nuts.setdir
+local setshift = nuts.setshift
local copy_node_list = nuts.copy_list
local hpack_node_list = nuts.hpack
@@ -819,11 +821,9 @@ function xtables.construct()
local list = drc.list
if list then
local w, h, d = getwhd(list)
- setfield(list,"shift",h+d)
+ setshift(list,h+d)
-- list = hpack_node_list(list) -- is somehow needed
- -- setfield(list,"width",0)
- -- setfield(list,"height",0)
- -- setfield(list,"depth",0)
+ -- setwhd(list,0,0,0)
-- faster:
local h = new_hlist(list)
list = h
@@ -872,7 +872,7 @@ function xtables.construct()
-- we have a direction issue here but hpack_node_list(list,0,"exactly","TLT") cannot be used
-- due to the fact that we need the width
local hbox = hpack_node_list(list)
- setfield(hbox,"dir","TLT")
+ setdir(hbox,"TLT")
result[nofr] = {
hbox,
size,
diff --git a/tex/context/base/mkiv/task-ini.lua b/tex/context/base/mkiv/task-ini.lua
index 59500c9b6..14d0b6e74 100644
--- a/tex/context/base/mkiv/task-ini.lua
+++ b/tex/context/base/mkiv/task-ini.lua
@@ -56,6 +56,7 @@ appendaction("processors", "fonts", "builders.kernel.ligaturing")
appendaction("processors", "fonts", "builders.kernel.kerning") -- always on (could be selective: if only node mode)
appendaction("processors", "fonts", "nodes.handlers.stripping") -- disabled (might move)
------------("processors", "fonts", "typesetters.italics.handler") -- disabled (after otf/kern handling)
+appendaction("processors", "fonts", "nodes.handlers.flatten")
appendaction("processors", "lists", "typesetters.rubies.check") -- disabled (maybe someplace else)
appendaction("processors", "lists", "typesetters.characteralign.handler") -- disabled (we need to to this after otf appliance)
@@ -65,8 +66,9 @@ appendaction("processors", "lists", "typesetters.digits.handler")
appendaction("processors", "lists", "typesetters.italics.handler") -- disabled (after otf/kern handling)
appendaction("processors", "lists", "languages.visualizediscretionaries") -- disabled
--- appendaction("processors", "lists", "typesetters.initials.handler") -- disabled
+appendaction ("processors", "after", "typesetters.marksuspects")
+appendaction("shipouts", "normalizers", "typesetters.showsuspects")
appendaction("shipouts", "normalizers", "typesetters.margins.finalhandler") -- disabled
------------("shipouts", "normalizers", "nodes.handlers.cleanuppage") -- disabled
appendaction("shipouts", "normalizers", "builders.paragraphs.expansion.trace") -- disabled
@@ -108,6 +110,7 @@ appendaction("math", "normalizers", "noads.handlers.resize", nil, "no
appendaction("math", "normalizers", "noads.handlers.alternates",nil, "nohead") -- always on
appendaction("math", "normalizers", "noads.handlers.tags", nil, "nohead") -- disabled
appendaction("math", "normalizers", "noads.handlers.italics", nil, "nohead") -- disabled
+appendaction("math", "normalizers", "noads.handlers.kernpairs", nil, "nohead") -- disabled
appendaction("math", "normalizers", "noads.handlers.classes", nil, "nohead") -- disabled
appendaction("math", "builders", "builders.kernel.mlist_to_hlist") -- always on
@@ -121,8 +124,13 @@ appendaction("finalizers", "lists", "builders.paragraphs.keeptogether")
------------("finalizers", "lists", "nodes.handlers.graphicvadjust") -- todo
appendaction("finalizers", "fonts", "builders.paragraphs.solutions.splitters.optimize") -- experimental
appendaction("finalizers", "lists", "builders.paragraphs.tag")
+
+-- the next can also be in contributers normalizers (when we remove the loop in the handler)
+
appendaction("finalizers", "lists", "nodes.linefillers.handler")
+appendaction("contributers", "normalizers", "nodes.handlers.flattenline")
+
-- still experimental
appendaction("mvlbuilders", "normalizers", "typesetters.margins.globalhandler") -- disabled
@@ -170,9 +178,12 @@ disableaction("processors", "typesetters.italics.handler")
disableaction("processors", "languages.visualizediscretionaries")
disableaction("processors", "nodes.handlers.stripping")
disableaction("processors", "builders.paragraphs.solutions.splitters.split")
-disableaction("processors", "nodes.rubies.check")
+disableaction("processors", "typesetters.rubies.check")
disableaction("processors", "typesetters.fontkerns.handler")
+disableaction("processors", "nodes.handlers.flatten")
+disableaction("processors", "typesetters.marksuspects")
+disableaction("shipouts", "typesetters.showsuspects")
disableaction("shipouts", "typesetters.margins.finalhandler")
disableaction("shipouts", "builders.paragraphs.expansion.trace")
disableaction("shipouts", "typesetters.alignments.handler")
@@ -192,8 +203,7 @@ disableaction("shipouts", "nodes.handlers.alignbackgrounds")
disableaction("shipouts", "nodes.references.handler")
disableaction("shipouts", "nodes.destinations.handler")
-------------("shipouts", "nodes.handlers.export")
-disableaction("shipouts","nodes.rubies.attach")
-
+disableaction("shipouts", "typesetters.rubies.attach")
disableaction("finalizers", "typesetters.margins.localhandler")
disableaction("finalizers", "builders.paragraphs.keeptogether")
@@ -202,9 +212,12 @@ disableaction("finalizers", "builders.paragraphs.solutions.splitters.optimize")
disableaction("finalizers", "builders.paragraphs.tag")
disableaction("finalizers", "nodes.linefillers.handler")
+disableaction("contributers","nodes.handlers.flattenline")
+
disableaction("math", "noads.handlers.showtree")
disableaction("math", "noads.handlers.tags")
disableaction("math", "noads.handlers.italics")
+disableaction("math", "noads.handlers.kernpairs")
disableaction("math", "noads.handlers.domains")
disableaction("math", "noads.handlers.classes")
disableaction("math", "noads.handlers.autofences")
diff --git a/tex/context/base/mkiv/toks-ini.lua b/tex/context/base/mkiv/toks-ini.lua
index 132605d38..0ce7b4836 100644
--- a/tex/context/base/mkiv/toks-ini.lua
+++ b/tex/context/base/mkiv/toks-ini.lua
@@ -68,7 +68,23 @@ local scan_csname = token.scan_csname
local get_next = token.get_next
+if not token.get_macro then
+ local scantoks = tex.scantoks
+ local gettoks = tex.gettoks
+ function token.get_meaning(name)
+ scantoks("t_get_macro",tex.ctxcatcodes,"\\"..name)
+ return gettoks("t_get_macro")
+ end
+ function token.get_macro(name)
+ scantoks("t_get_macro",tex.ctxcatcodes,"\\"..name)
+ local s = gettoks("t_get_macro")
+ return match(s,"^.-%->(.*)$") or s
+ end
+end
+
local set_macro = token.set_macro
+local get_macro = token.get_macro
+local get_meaning = token.get_meaning
local get_cmdname = token.get_cmdname
local create_token = token.create
@@ -238,14 +254,16 @@ tokens.scanners = { -- these expand
}
tokens.getters = { -- these don't expand
- token = get_next,
- count = tex.getcount,
- dimen = tex.getdimen,
- skip = tex.getglue,
- glue = tex.getglue,
- skip = tex.getmuglue,
- glue = tex.getmuglue,
- box = tex.getbox,
+ meaning = get_meaning,
+ macro = get_macro,
+ token = get_next,
+ count = tex.getcount,
+ dimen = tex.getdimen,
+ skip = tex.getglue,
+ glue = tex.getglue,
+ skip = tex.getmuglue,
+ glue = tex.getmuglue,
+ box = tex.getbox,
}
tokens.setters = {
diff --git a/tex/context/base/mkiv/toks-ini.mkiv b/tex/context/base/mkiv/toks-ini.mkiv
index 03ec99742..aaa735207 100644
--- a/tex/context/base/mkiv/toks-ini.mkiv
+++ b/tex/context/base/mkiv/toks-ini.mkiv
@@ -13,13 +13,13 @@
\writestatus{loading}{ConTeXt Token Support / Initialization}
+\unprotect
+
+\newtoks\t_get_macro % will go away
+
\registerctxluafile{toks-ini}{1.001}
\registerctxluafile{toks-scn}{1.001}
\registerctxluafile{cldf-scn}{1.001}
\registerctxluafile{cldf-stp}{1.001}
-\unprotect
-
-% nothing yet
-
\protect \endinput
diff --git a/tex/context/base/mkiv/toks-scn.lua b/tex/context/base/mkiv/toks-scn.lua
index 696478144..3c41eedd8 100644
--- a/tex/context/base/mkiv/toks-scn.lua
+++ b/tex/context/base/mkiv/toks-scn.lua
@@ -153,8 +153,25 @@ tokens.converters = {
toglue = "todimen",
}
+-- We could just pickup a keyword but then we really need to make sure
+-- that no number follows it when that is the assignment and adding
+-- an optional = defeats the gain in speed. Currently we have sources
+-- with no spaces (\startcontextdefinitioncode ...) so it fails there.
+--
+-- Another drawback is that we then need to use { } instead of ending
+-- with \relax (as we can do now) but that is no big deal. It's just
+-- that I then need to check the TeX end. More pain than gain and a bit
+-- risky too.
+
local f_if = formatters[ " if scankeyword('%s') then data['%s'] = scan%s()"]
local f_elseif = formatters[" elseif scankeyword('%s') then data['%s'] = scan%s()"]
+
+----- f_if = formatters[" local key = scanword() if key == '' then break elseif key == '%s' then data['%s'] = scan%s()"]
+----- f_elseif = formatters[" elseif key == '%s' then data['%s'] = scan%s()"]
+
+----- f_if_x = formatters[ " if not data['%s'] and scankeyword('%s') then data['%s'] = scan%s()"]
+----- f_elseif_x = formatters[" elseif not data['%s'] and scankeyword('%s') then data['%s'] = scan%s()"]
+
local f_local = formatters["local scan%s = scanners.%s"]
local f_scan = formatters["scan%s()"]
local f_shortcut = formatters["local %s = scanners.converters.%s"]
@@ -163,6 +180,11 @@ local f_if_c = formatters[ " if scankeyword('%s') then data['%s'] = %s(s
local f_elseif_c = formatters[" elseif scankeyword('%s') then data['%s'] = %s(scan%s())"]
local f_scan_c = formatters["%s(scan%s())"]
+-- see above
+--
+----- f_if_c = formatters[" local key = scanword() if key == '' then break elseif key == '%s' then data['%s'] = %s(scan%s())"]
+----- f_elseif_c = formatters[" elseif k == '%s' then data['%s'] = %s(scan%s())"]
+
local f_any = formatters[" else local key = scanword() if key then data[key] = scan%s() else break end end"]
local f_any_c = formatters[" else local key = scanword() if key then data[key] = %s(scan%s()) else break end end"]
local s_done = " else break end"
@@ -269,6 +291,7 @@ function tokens.compile(specification)
else
m = m + 1
r[m] = (m > 1 and f_elseif or f_if )(t1,t1,t2)
+ -- r[m] = (m > 1 and f_elseif_x or f_if_x)(t1,t1,t1,t2)
end
end
end
@@ -291,9 +314,9 @@ function tokens.compile(specification)
end
tokens._action = a
for i=1,#a do
- code = f_action_f(i,code)
--- f[#f+1] = f_action_s(i,i)
-n = n + 1 f[n] = f_action_s(i,i)
+ code = f_action_f(i,code)
+ n = n + 1
+ f[n] = f_action_s(i,i)
end
code = f_simple(f,code)
else
@@ -309,9 +332,9 @@ n = n + 1 f[n] = f_action_s(i,i)
if a then
tokens._action = a
for i=1,#a do
- code = f_action_f(i,code)
--- f[#f+1] = f_action_s(i,i)
-n = n + 1 f[n] = f_action_s(i,i)
+ code = f_action_f(i,code)
+ n = n + 1
+ f[n] = f_action_s(i,i)
end
end
code = f_table(f,ti,code)
@@ -319,9 +342,9 @@ n = n + 1 f[n] = f_action_s(i,i)
code = f_scan(ti)
tokens._action = a
for i=1,#a do
- code = f_action_f(i,code)
--- f[#f+1] = f_action_s(i,i)
-n = n + 1 f[n] = f_action_s(i,i)
+ code = f_action_f(i,code)
+ n = n + 1
+ f[n] = f_action_s(i,i)
end
code = f_simple(f,code)
else
@@ -367,9 +390,9 @@ n = n + 1 f[n] = f_action_s(i,i)
if a then
tokens._action = a
for i=1,#a do
- code = f_action_f(i,code)
--- f[#f+1] = f_action_s(i,i)
-n = n + 1 f[n] = f_action_s(i,i)
+ code = f_action_f(i,code)
+ n = n + 1
+ f[n] = f_action_s(i,i)
end
end
code = f_sequence(c,f,p,code)
diff --git a/tex/context/base/mkiv/trac-deb.lua b/tex/context/base/mkiv/trac-deb.lua
index 3770f4189..782be154f 100644
--- a/tex/context/base/mkiv/trac-deb.lua
+++ b/tex/context/base/mkiv/trac-deb.lua
@@ -337,26 +337,22 @@ local function trace_calls(n)
trace_calls = function() end
end
-if LUATEXVERSION > 0.98 then
+local editor = [[scite "-open:%filename%" -goto:%linenumber%]]
- local editor = [[scite "-open:%filename%" -goto:%linenumber%]]
-
- directives.register("system.editor",function(v)
- editor = v
- end)
-
- callback.register("call_edit",function(filename,linenumber)
- if editor then
- editor = gsub(editor,"%%s",filename)
- editor = gsub(editor,"%%d",linenumber)
- editor = gsub(editor,"%%filename%%",filename)
- editor = gsub(editor,"%%linenumber%%",linenumber)
- logs.report("system","starting editor: %s",editor)
- os.execute(editor)
- end
- end)
+directives.register("system.editor",function(v)
+ editor = v
+end)
-end
+callback.register("call_edit",function(filename,linenumber)
+ if editor then
+ editor = gsub(editor,"%%s",filename)
+ editor = gsub(editor,"%%d",linenumber)
+ editor = gsub(editor,"%%filename%%",filename)
+ editor = gsub(editor,"%%linenumber%%",linenumber)
+ logs.report("system","starting editor: %s",editor)
+ os.execute(editor)
+ end
+end)
directives.register("system.tracecalls", function(n) trace_calls(n) end) -- indirect is needed for nilling
diff --git a/tex/context/base/mkiv/trac-inf.lua b/tex/context/base/mkiv/trac-inf.lua
index 12a4f646f..2aecb6703 100644
--- a/tex/context/base/mkiv/trac-inf.lua
+++ b/tex/context/base/mkiv/trac-inf.lua
@@ -42,11 +42,53 @@ local function resettiming(instance)
timers[instance or "notimer"] = { timing = 0, loadtime = 0 }
end
+local ticks = clock
+local seconds = function(n) return n or 0 end
+
+-- local okay, ffi = pcall(require,"ffi")
+--
+-- if ffi and os.type == "windows" then
+--
+-- local okay, kernel = pcall(ffi.load,"kernel32")
+--
+-- if kernel then
+--
+-- local tonumber = ffi.number or tonumber
+--
+-- ffi.cdef[[
+-- int QueryPerformanceFrequency(int64_t *lpFrequency);
+-- int QueryPerformanceCounter(int64_t *lpPerformanceCount);
+-- ]]
+--
+-- local target = ffi.new("__int64[1]")
+--
+-- ticks = function()
+-- if kernel.QueryPerformanceCounter(target) == 1 then
+-- return tonumber(target[0])
+-- else
+-- return 0
+-- end
+-- end
+--
+-- local target = ffi.new("__int64[1]")
+--
+-- seconds = function(ticks)
+-- if kernel.QueryPerformanceFrequency(target) == 1 then
+-- return ticks / tonumber(target[0])
+-- else
+-- return 0
+-- end
+-- end
+--
+-- end
+--
+-- end
+
local function starttiming(instance)
local timer = timers[instance or "notimer"]
local it = timer.timing or 0
if it == 0 then
- timer.starttime = clock()
+ timer.starttime = ticks()
if not timer.loadtime then
timer.loadtime = 0
end
@@ -62,7 +104,7 @@ local function stoptiming(instance)
else
local starttime = timer.starttime
if starttime and starttime > 0 then
- local stoptime = clock()
+ local stoptime = ticks()
local loadtime = stoptime - starttime
timer.stoptime = stoptime
timer.loadtime = timer.loadtime + loadtime
@@ -79,7 +121,7 @@ local function elapsed(instance)
return instance or 0
else
local timer = timers[instance or "notimer"]
- return timer and timer.loadtime or 0
+ return timer and seconds(timer.loadtime) or 0
end
end
@@ -137,10 +179,13 @@ function statistics.show()
local total, indirect = status.callbacks or 0, status.indirect_callbacks or 0
return format("%s direct, %s indirect, %s total", total-indirect, indirect, total)
end)
- if jit then
- local jitstatus = { jit.status() }
- if jitstatus[1] then
- register("luajit options", concat(jitstatus," ",2))
+ if TEXENGINE == "luajittex" and JITSUPPORTED then
+ local jitstatus = jit.status
+ if jitstatus then
+ local jitstatus = { jitstatus() }
+ if jitstatus[1] then
+ register("luajit options", concat(jitstatus," ",2))
+ end
end
end
-- so far
diff --git a/tex/context/base/mkiv/trac-jus.lua b/tex/context/base/mkiv/trac-jus.lua
index 76d6438a1..6d00bf19e 100644
--- a/tex/context/base/mkiv/trac-jus.lua
+++ b/tex/context/base/mkiv/trac-jus.lua
@@ -23,11 +23,13 @@ local getlist = nuts.getlist
local getattr = nuts.getattr
local setattr = nuts.setattr
local setlist = nuts.setlist
+local setlink = nuts.setlink
+local getwidth = nuts.getwidth
+local findtail = nuts.tail
local traverse_id = nuts.traverse_id
local list_dimensions = nuts.dimensions
-local linked_nodes = nuts.linked
-local copy_node = nuts.copy
+local copy_list = nuts.copy_list
local tracedrule = nodes.tracers.pool.nuts.rule
@@ -41,12 +43,14 @@ local hlist_code = nodes.nodecodes.hlist
local texsetattribute = tex.setattribute
local unsetvalue = attributes.unsetvalue
+local enableaction = nodes.tasks.enableaction
+
local min_threshold = 0
local max_threshold = 0
local function set(n)
- nodes.tasks.enableaction("mvlbuilders", "typesetters.checkers.handler")
- nodes.tasks.enableaction("vboxbuilders","typesetters.checkers.handler")
+ enableaction("mvlbuilders", "typesetters.checkers.handler")
+ enableaction("vboxbuilders","typesetters.checkers.handler")
texsetattribute(a_justification,n or 1)
function typesetters.checkers.set(n)
texsetattribute(a_justification,n or 1)
@@ -77,7 +81,7 @@ function checkers.handler(head)
for current in traverse_id(hlist_code,tonut(head)) do
if getattr(current,a_justification) == 1 then
setattr(current,a_justification,0) -- kind of reset
- local width = getfield(current,"width")
+ local width = getwidth(current)
if width > 0 then
local list = getlist(current)
if list then
@@ -86,23 +90,29 @@ function checkers.handler(head)
if naturalwidth == 0 or delta == 0 then
-- special box
elseif delta >= max_threshold then
- local rule = tracedrule(delta,naturalheight,naturaldepth,getfield(list,"glue_set") == 1 and "trace:dr" or "trace:db")
- setlist(current,linked_nodes(list,new_hlist(rule)))
+ local rule = new_hlist(tracedrule(delta,naturalheight,naturaldepth,getfield(list,"glue_set") == 1 and "trace:dr" or "trace:db"))
+ setlink(findtail(list),rule)
+ setlist(current,list)
elseif delta <= min_threshold then
local alignstate = getattr(list,a_alignstate)
if alignstate == 1 then
- local rule = tracedrule(-delta,naturalheight,naturaldepth,"trace:dc")
- setlist(current,linked_nodes(new_hlist(rule),list))
+ local rule = new_hlist(tracedrule(-delta,naturalheight,naturaldepth,"trace:dc"))
+ setlink(rule,list)
+ setlist(current,rule)
elseif alignstate == 2 then
- local lrule = tracedrule(-delta/2,naturalheight,naturaldepth,"trace:dy")
- local rrule = copy_node(lrule)
- setlist(current,linked_nodes(new_hlist(lrule),list,new_kern(delta/2),new_hlist(rrule)))
+ local lrule = new_hlist(tracedrule(-delta/2,naturalheight,naturaldepth,"trace:dy"))
+ local rrule = copy_list(lrule)
+ setlink(lrule,list)
+ setlink(findtail(list),new_kern(delta/2),rrule)
+ setlist(current,lrule)
elseif alignstate == 3 then
- local rule = tracedrule(-delta,naturalheight,naturaldepth,"trace:dm")
- setlist(current,linked_nodes(list,new_kern(delta),new_hlist(rule)))
+ local rule = new_hlist(tracedrule(-delta,naturalheight,naturaldepth,"trace:dm"))
+ setlink(findtail(list),new_kern(delta),rule)
+ setlist(current,list)
else
- local rule = tracedrule(-delta,naturalheight,naturaldepth,"trace:dg")
- setlist(current,linked_nodes(list,new_kern(delta),new_hlist(rule)))
+ local rule = new_hlist(tracedrule(-delta,naturalheight,naturaldepth,"trace:dg"))
+ setlink(findtail(list),new_kern(delta),rule)
+ setlist(current,list)
end
end
end
diff --git a/tex/context/base/mkiv/trac-par.lua b/tex/context/base/mkiv/trac-par.lua
index 3d8909eb4..56291f8c8 100644
--- a/tex/context/base/mkiv/trac-par.lua
+++ b/tex/context/base/mkiv/trac-par.lua
@@ -21,6 +21,7 @@ local getnext = nuts.getnext
local getlist = nuts.getlist
local getfont = nuts.getfont
local getchar = nuts.getchar
+local getwidth = nuts.getwidth
local nodecodes = nodes.nodecodes
local hlist_code = nodecodes.hlist
@@ -30,6 +31,8 @@ local setnodecolor = nodes.tracers.colors.set
local parameters = fonts.hashes.parameters
local basepoints = number.basepoints
+local setaction = nodes.tasks.setaction
+
-- definecolor[hz:positive] [r=0.6]
-- definecolor[hz:negative] [g=0.6]
-- definecolor[hz:zero] [b=0.6]
@@ -98,7 +101,7 @@ local function colorize(n)
if trace_verbose then
length = length + 1
list[length] = utfchar(getchar(n))
- width = width + getfield(n,"width") -- no kerning yet
+ width = width + getwidth(n) -- no kerning yet
end
end
end
@@ -126,17 +129,8 @@ function builders.paragraphs.expansion.trace(head)
return head
end
-local tasks = nodes.tasks
-
--- tasks.prependaction("shipouts","normalizers","builders.paragraphs.expansion.trace")
--- tasks.disableaction("shipouts","builders.paragraphs.expansion.trace")
-
local function set(v)
- if v then
- tasks.enableaction("shipouts","builders.paragraphs.expansion.trace")
- else
- tasks.disableaction("shipouts","builders.paragraphs.expansion.trace")
- end
+ setaction("shipouts","builders.paragraphs.expansion.trace",v)
end
trackers.register("builders.paragraphs.expansion.verbose",set)
diff --git a/tex/context/base/mkiv/trac-vis.lua b/tex/context/base/mkiv/trac-vis.lua
index 52ab3e935..8cca4752b 100644
--- a/tex/context/base/mkiv/trac-vis.lua
+++ b/tex/context/base/mkiv/trac-vis.lua
@@ -76,6 +76,8 @@ local setlist = nuts.setlist
local setleader = nuts.setleader
local setsubtype = nuts.setsubtype
local setattr = nuts.setattr
+local setwidth = nuts.setwidth
+local setshift = nuts.setshift
local getfield = nuts.getfield
local getid = nuts.getid
@@ -91,6 +93,11 @@ local getprev = nuts.getprev
local getboth = nuts.getboth
local getdisc = nuts.getdisc
local getwhd = nuts.getwhd
+local getkern = nuts.getkern
+local getpenalty = nuts.getpenalty
+local getdir = nuts.getdir
+local getwidth = nuts.getwidth
+local getshift = nuts.getshift
local hpack_nodes = nuts.hpack
local vpack_nodes = nuts.vpack
@@ -99,9 +106,8 @@ local flush_node_list = nuts.flush_list
local insert_node_before = nuts.insert_before
local insert_node_after = nuts.insert_after
local traverse_nodes = nuts.traverse
-local linked_nodes = nuts.linked
local apply_to_nodes = nuts.apply
-
+local find_tail = nuts.tail
local effectiveglue = nuts.effective_glue
local hpack_string = nuts.typesetters.tohpack
@@ -146,6 +152,8 @@ local bit = number.bit
local setbit = number.setbit
local clearbit = number.clearbit
+local enableaction = nodes.tasks.enableaction
+
local trace_hbox
local trace_vbox
local trace_vtop
@@ -158,33 +166,35 @@ local trace_whatsit
local trace_user
local trace_math
local trace_italic
+local trace_discretionary
local report_visualize = logs.reporter("visualize")
local modes = {
- hbox = 1,
- vbox = 2,
- vtop = 4,
- kern = 8,
- glue = 16,
- -- skip = 16,
- penalty = 32,
- fontkern = 64,
- strut = 128,
- whatsit = 256,
- glyph = 512,
- simple = 1024,
- simplehbox = 1024 + 1,
- simplevbox = 1024 + 2,
- simplevtop = 1024 + 4,
- user = 2048,
- math = 4096,
- italic = 8192,
- origin = 16384,
+ hbox = 1,
+ vbox = 2,
+ vtop = 4,
+ kern = 8,
+ glue = 16,
+ -- skip = 16,
+ penalty = 32,
+ fontkern = 64,
+ strut = 128,
+ whatsit = 256,
+ glyph = 512,
+ simple = 1024,
+ simplehbox = 1024 + 1,
+ simplevbox = 1024 + 2,
+ simplevtop = 1024 + 4,
+ user = 2048,
+ math = 4096,
+ italic = 8192,
+ origin = 16384,
+ discretionary = 32768,
}
local usedfont, exheight, emwidth
-local l_penalty, l_glue, l_kern, l_fontkern, l_hbox, l_vbox, l_vtop, l_strut, l_whatsit, l_glyph, l_user, l_math, l_italic, l_origin
+local l_penalty, l_glue, l_kern, l_fontkern, l_hbox, l_vbox, l_vtop, l_strut, l_whatsit, l_glyph, l_user, l_math, l_italic, l_origin, l_discretionary
local enabled = false
local layers = { }
@@ -219,21 +229,22 @@ local function enable()
}
layers[mode] = attributes.viewerlayers.register(tag,true)
end
- l_hbox = layers.hbox
- l_vbox = layers.vbox
- l_vtop = layers.vtop
- l_glue = layers.glue
- l_kern = layers.kern
- l_penalty = layers.penalty
- l_fontkern = layers.fontkern
- l_strut = layers.strut
- l_whatsit = layers.whatsit
- l_glyph = layers.glyph
- l_user = layers.user
- l_math = layers.math
- l_italic = layers.italic
- l_origin = layers.origin
- nodes.tasks.enableaction("shipouts","nodes.visualizers.handler")
+ l_hbox = layers.hbox
+ l_vbox = layers.vbox
+ l_vtop = layers.vtop
+ l_glue = layers.glue
+ l_kern = layers.kern
+ l_penalty = layers.penalty
+ l_fontkern = layers.fontkern
+ l_strut = layers.strut
+ l_whatsit = layers.whatsit
+ l_glyph = layers.glyph
+ l_user = layers.user
+ l_math = layers.math
+ l_italic = layers.italic
+ l_origin = layers.origin
+ l_discretionary = layers.discretionary
+ enableaction("shipouts","nodes.visualizers.handler")
report_visualize("enabled")
enabled = true
tex.setcount("global","c_syst_visualizers_state",1) -- so that we can optimize at the tex end
@@ -332,35 +343,37 @@ trackers .register("visualizers.makeup", function(v) set("makeup",v) end)
trackers .register("visualizers.boxes", function(v) set("boxes", v) end)
directives.register("visualizers.fraction", function(v) fraction = (v and tonumber(v)) or (v == "more" and 5) or 10 end)
-local c_positive = "trace:b"
-local c_negative = "trace:r"
-local c_zero = "trace:g"
-local c_text = "trace:s"
-local c_space = "trace:y"
-local c_skip_a = "trace:c"
-local c_skip_b = "trace:m"
-local c_glyph = "trace:o"
-local c_ligature = "trace:s"
-local c_white = "trace:w"
-local c_math = "trace:r"
-local c_origin = "trace:o"
-
-local c_positive_d = "trace:db"
-local c_negative_d = "trace:dr"
-local c_zero_d = "trace:dg"
-local c_text_d = "trace:ds"
-local c_space_d = "trace:dy"
-local c_skip_a_d = "trace:dc"
-local c_skip_b_d = "trace:dm"
-local c_glyph_d = "trace:do"
-local c_ligature_d = "trace:ds"
-local c_white_d = "trace:dw"
-local c_math_d = "trace:dr"
-local c_origin_d = "trace:do"
+local c_positive = "trace:b"
+local c_negative = "trace:r"
+local c_zero = "trace:g"
+local c_text = "trace:s"
+local c_space = "trace:y"
+local c_skip_a = "trace:c"
+local c_skip_b = "trace:m"
+local c_glyph = "trace:o"
+local c_ligature = "trace:s"
+local c_white = "trace:w"
+local c_math = "trace:r"
+local c_origin = "trace:o"
+local c_discretionary = "trace:o"
+
+local c_positive_d = "trace:db"
+local c_negative_d = "trace:dr"
+local c_zero_d = "trace:dg"
+local c_text_d = "trace:ds"
+local c_space_d = "trace:dy"
+local c_skip_a_d = "trace:dc"
+local c_skip_b_d = "trace:dm"
+local c_glyph_d = "trace:do"
+local c_ligature_d = "trace:ds"
+local c_white_d = "trace:dw"
+local c_math_d = "trace:dr"
+local c_origin_d = "trace:do"
+local c_discretionary_d = "trace:do"
local function sometext(str,layer,color,textcolor,lap) -- we can just paste verbatim together .. no typesteting needed
local text = hpack_string(str,usedfont)
- local size = getfield(text,"width")
+ local size = getwidth(text)
local rule = new_rule(size,2*exheight,exheight/2)
local kern = new_kern(-size)
if color then
@@ -369,12 +382,14 @@ local function sometext(str,layer,color,textcolor,lap) -- we can just paste verb
if textcolor then
setlistcolor(getlist(text),textcolor)
end
- local info = linked_nodes(rule,kern,text)
+ local info = setlink(rule,kern,text)
setlisttransparency(info,c_zero)
info = hpack_nodes(info)
- local width = getfield(info,"width")
+ local width = getwidth(info)
if lap then
- info = new_hlist(linked_nodes(new_kern(-width),info))
+ info = new_hlist(setlink(new_kern(-width),info))
+ else
+ info = new_hlist(info)
end
if layer then
setattr(info,a_layer,layer)
@@ -382,476 +397,535 @@ local function sometext(str,layer,color,textcolor,lap) -- we can just paste verb
return info, width
end
-local f_cache = { }
+local caches = table.setmetatableindex("table")
-local function fontkern(head,current)
- local width = getfield(current,"kern")
- local extra = getfield(current,"expansion_factor")
- local kern = width + extra
- local info = f_cache[kern]
- -- report_visualize("fontkern: %p ex %p",width,extra)
- if info then
- -- print("hit fontkern")
- else
- local text = hpack_string(formatters[" %0.3f"](kern*pt_factor),usedfont)
- local rule = new_rule(emwidth/fraction,6*exheight,2*exheight)
- local list = getlist(text)
- if kern > 0 then
- setlistcolor(list,c_positive_d)
- elseif kern < 0 then
- setlistcolor(list,c_negative_d)
+local fontkern do
+
+ local f_cache = caches["fontkern"]
+
+ fontkern = function(head,current)
+ local width = getkern(current)
+ local extra = getfield(current,"expansion_factor")
+ local kern = width + extra
+ local info = f_cache[kern]
+ -- report_visualize("fontkern: %p ex %p",width,extra)
+ if info then
+ -- print("hit fontkern")
else
- setlistcolor(list,c_zero_d)
+ local text = hpack_string(formatters[" %0.3f"](kern*pt_factor),usedfont)
+ local rule = new_rule(emwidth/fraction,6*exheight,2*exheight)
+ local list = getlist(text)
+ if kern > 0 then
+ setlistcolor(list,c_positive_d)
+ elseif kern < 0 then
+ setlistcolor(list,c_negative_d)
+ else
+ setlistcolor(list,c_zero_d)
+ end
+ setlisttransparency(list,c_text_d)
+ settransparency(rule,c_text_d)
+ setshift(text,-5 * exheight)
+ info = new_hlist(setlink(rule,text))
+ setattr(info,a_layer,l_fontkern)
+ f_cache[kern] = info
end
- setlisttransparency(list,c_text_d)
- settransparency(rule,c_text_d)
- setfield(text,"shift",-5 * exheight)
- info = new_hlist(linked_nodes(rule,text))
- setattr(info,a_layer,l_fontkern)
- f_cache[kern] = info
+ head = insert_node_before(head,current,copy_list(info))
+ return head, current
end
- head = insert_node_before(head,current,copy_list(info))
- return head, current
+
end
-local w_cache = { }
-local tags = {
- open = "FIC",
- write = "FIW",
- close = "FIC",
- special = "SPE",
- latelua = "LUA",
- savepos = "POS",
- userdefined = "USR",
- -- backend stuff
- pdfliteral = "PDF",
- pdfrefobj = "PDF",
- pdfannot = "PDF",
- pdfstartlink = "PDF",
- pdfendlink = "PDF",
- pdfdest = "PDF",
- pdfthread = "PDF",
- pdfstartthread = "PDF",
- pdfendthread = "PDF",
- pdfthreaddata = "PDF",
- pdflinkdata = "PDF",
- pdfcolorstack = "PDF",
- pdfsetmatrix = "PDF",
- pdfsave = "PDF",
- pdfrestore = "PDF",
-}
+local whatsit do
+
+ local w_cache = caches["whatsit"]
+
+ local tags = {
+ open = "FIC",
+ write = "FIW",
+ close = "FIC",
+ special = "SPE",
+ latelua = "LUA",
+ savepos = "POS",
+ userdefined = "USR",
+ -- backend stuff
+ pdfliteral = "PDF",
+ pdfrefobj = "PDF",
+ pdfannot = "PDF",
+ pdfstartlink = "PDF",
+ pdfendlink = "PDF",
+ pdfdest = "PDF",
+ pdfthread = "PDF",
+ pdfstartthread = "PDF",
+ pdfendthread = "PDF",
+ pdfthreaddata = "PDF",
+ pdflinkdata = "PDF",
+ pdfcolorstack = "PDF",
+ pdfsetmatrix = "PDF",
+ pdfsave = "PDF",
+ pdfrestore = "PDF",
+ }
-local function whatsit(head,current)
- local what = getsubtype(current)
- local info = w_cache[what]
- if info then
- -- print("hit whatsit")
- else
- local tag = whatsitcodes[what]
- -- maybe different text colors per tag
- info = sometext(formatters["W:%s"](tag and tags[tag] or what),usedfont,nil,c_white)
- setattr(info,a_layer,l_whatsit)
- w_cache[what] = info
+ whatsit = function(head,current)
+ local what = getsubtype(current)
+ local info = w_cache[what]
+ if info then
+ -- print("hit whatsit")
+ else
+ local tag = whatsitcodes[what]
+ -- maybe different text colors per tag
+ info = sometext(formatters["W:%s"](tag and tags[tag] or what),usedfont,nil,c_white)
+ setattr(info,a_layer,l_whatsit)
+ w_cache[what] = info
+ end
+ head, current = insert_node_after(head,current,copy_list(info))
+ return head, current
end
- head, current = insert_node_after(head,current,copy_list(info))
- return head, current
+
end
-local u_cache = { }
+local user do
-local function user(head,current)
- local what = getsubtype(current)
- local info = u_cache[what]
- if info then
- -- print("hit user")
- else
- info = sometext(formatters["U:%s"](what),usedfont)
- setattr(info,a_layer,l_user)
- u_cache[what] = info
+ local u_cache = caches["user"]
+
+ user = function(head,current)
+ local what = getsubtype(current)
+ local info = u_cache[what]
+ if info then
+ -- print("hit user")
+ else
+ info = sometext(formatters["U:%s"](what),usedfont)
+ setattr(info,a_layer,l_user)
+ u_cache[what] = info
+ end
+ head, current = insert_node_after(head,current,copy_list(info))
+ return head, current
end
- head, current = insert_node_after(head,current,copy_list(info))
- return head, current
+
end
-local m_cache = {
- beginmath = { },
- endmath = { },
-}
-local tags = {
- beginmath = "B",
- endmath = "E",
-}
+local math do
-local function math(head,current)
- local what = getsubtype(current)
- local tag = mathcodes[what]
- local skip = getfield(current,"surround") + getfield(current,"width")
- local info = m_cache[tag][skip]
- if info then
- -- print("hit math")
- else
- local text, width = sometext(formatters["M:%s"](tag and tags[tag] or what),usedfont,nil,c_math_d)
- local rule = new_rule(skip,-655360/fraction,2*655360/fraction)
- setcolor(rule,c_math_d)
- settransparency(rule,c_math_d)
- setattr(rule,a_layer,l_math)
- if tag == "beginmath" then
- info = new_hlist(linked_nodes(new_glue(-skip),rule,new_glue(-width),text))
+ local m_cache = {
+ b_cache = caches["bmath"],
+ e_cache = caches["emath"],
+ }
+
+ local tags = {
+ beginmath = "B",
+ endmath = "E",
+ }
+
+ math = function(head,current)
+ local what = getsubtype(current)
+ local tag = mathcodes[what]
+ local skip = getkern(current) + getwidth(current) -- surround
+ local info = m_cache[tag][skip]
+ if info then
+ -- print("hit math")
else
- info = new_hlist(linked_nodes(new_glue(-skip),rule,new_glue(-skip),text))
+ local text, width = sometext(formatters["M:%s"](tag and tags[tag] or what),usedfont,nil,c_math_d)
+ local rule = new_rule(skip,-655360/fraction,2*655360/fraction)
+ setcolor(rule,c_math_d)
+ settransparency(rule,c_math_d)
+ setattr(rule,a_layer,l_math)
+ if tag == "beginmath" then
+ info = new_hlist(setlink(new_glue(-skip),rule,new_glue(-width),text))
+ else
+ info = new_hlist(setlink(new_glue(-skip),rule,new_glue(-skip),text))
+ end
+ setattr(info,a_layer,l_math)
+ m_cache[tag][skip] = info
end
- setattr(info,a_layer,l_math)
- m_cache[tag][skip] = info
+ head, current = insert_node_after(head,current,copy_list(info))
+ return head, current
end
- head, current = insert_node_after(head,current,copy_list(info))
- return head, current
+
end
-local b_cache = { }
+local ruledbox do
-local o_cache = table.setmetatableindex(function(t,size)
- local rule = new_rule(2*size,size,size)
- origin = hpack_nodes(rule)
- setcolor(rule,c_origin_d)
- settransparency(rule,c_origin_d)
- setattr(rule,a_layer,l_origin)
- t[size] = origin
- return origin
-end)
+ local b_cache = caches["box"]
+ local o_cache = caches["origin"]
-local function ruledbox(head,current,vertical,layer,what,simple,previous,trace_origin,parent)
- local wd, ht, dp = getwhd(current)
- if wd ~= 0 then
- local shift = getfield(current,"shift")
- local dir = getfield(current,"dir")
--- if dir == "LTL" or dir == "RRT" then
--- wd, ht, dp = ht + dp, wd, 0
--- end
- local next = getnext(current)
- local prev = previous
- -- local prev = getprev(current) -- prev can be wrong in math mode < 0.78.3
- setboth(current)
- local linewidth = emwidth/fraction
- local size = 2*linewidth
- local baseline, baseskip
- if dp ~= 0 and ht ~= 0 then
- if wd > 20*linewidth then
- baseline = b_cache.baseline
- if not baseline then
- -- due to an optimized leader color/transparency we need to set the glue node in order
- -- to trigger this mechanism
- local leader = linked_nodes(new_glue(size),new_rule(3*size,linewidth,0),new_glue(size))
- leader = hpack_nodes(leader)
- baseline = new_glue(0)
- setleader(baseline,leader)
- setsubtype(baseline,cleaders_code)
- setfield(baseline,"stretch",65536)
- setfield(baseline,"stretch_order",2)
- setlisttransparency(baseline,c_text)
- b_cache.baseline = baseline
+ table.setmetatableindex(o_cache,function(t,size)
+ local rule = new_rule(2*size,size,size)
+ local origin = hpack_nodes(rule)
+ setcolor(rule,c_origin_d)
+ settransparency(rule,c_origin_d)
+ setattr(rule,a_layer,l_origin)
+ t[size] = origin
+ return origin
+ end)
+
+ ruledbox = function(head,current,vertical,layer,what,simple,previous,trace_origin,parent)
+ local wd, ht, dp = getwhd(current)
+ if wd ~= 0 then
+ local shift = getshift(current)
+ local dir = getdir(current)
+ -- if dir == "LTL" or dir == "RRT" then
+ -- wd, ht, dp = ht + dp, wd, 0
+ -- end
+ local next = getnext(current)
+ local prev = previous
+ -- local prev = getprev(current) -- prev can be wrong in math mode < 0.78.3
+ setboth(current)
+ local linewidth = emwidth/fraction
+ local size = 2*linewidth
+ local baseline, baseskip
+ if dp ~= 0 and ht ~= 0 then
+ if wd > 20*linewidth then
+ baseline = b_cache[size]
+ if not baseline then
+ -- due to an optimized leader color/transparency we need to set the glue node in order
+ -- to trigger this mechanism
+ local leader = setlink(new_glue(size),new_rule(3*size,linewidth,0),new_glue(size))
+ leader = hpack_nodes(leader)
+ baseline = new_glue(0,65536,0,2,0)
+ setleader(baseline,leader)
+ setsubtype(baseline,cleaders_code)
+ setlisttransparency(baseline,c_text)
+ baseline = hpack_nodes(baseline,wd-size)
+ b_cache[size] = baseline
+ end
+ baseline = copy_list(baseline)
+ baseskip = new_kern(-wd+linewidth)
+ else
+ baseline = new_rule(wd-size,linewidth,0)
+ baseskip = new_kern(-wd+size)
end
- baseline = copy_list(baseline)
- baseline = hpack_nodes(baseline,wd-size)
- -- or new_hlist, set head and also:
- -- baseline.width = wd
- -- baseline.glue_set = wd/65536
- -- baseline.glue_order = 2
- -- baseline.glue_sign = 1
- baseskip = new_kern(-wd+linewidth)
- else
- baseline = new_rule(wd-size,linewidth,0)
- baseskip = new_kern(-wd+size)
end
- end
- local this
- if not simple then
- this = b_cache[what]
- if not this then
- local text = hpack_string(what,usedfont)
- this = linked_nodes(new_kern(-getfield(text,"width")),text)
- setlisttransparency(this,c_text)
- this = new_hlist(this)
- b_cache[what] = this
+ local this
+ if not simple then
+ this = b_cache[what]
+ if not this then
+ local text = hpack_string(what,usedfont)
+ this = setlink(new_kern(-getwidth(text)),text)
+ setlisttransparency(this,c_text)
+ this = new_hlist(this)
+ b_cache[what] = this
+ end
end
- end
- -- we need to trigger the right mode (else sometimes no whatits)
- local info = linked_nodes(
- this and copy_list(this) or nil,
- new_rule(linewidth,ht,dp),
- new_rule(wd-size,-dp+linewidth,dp),
- new_rule(linewidth,ht,dp),
- new_kern(-wd+linewidth),
- new_rule(wd-size,ht,-ht+linewidth)
- )
- if baseskip then
- info = linked_nodes(info,baseskip,baseline) -- could be in previous linked
- end
- setlisttransparency(info,c_text)
- info = new_hlist(info)
- --
- setattr(info,a_layer,layer)
- if vertical then
- if shift == 0 then
- info = linked_nodes(current,dp ~= 0 and new_kern(-dp) or nil,info)
- elseif trace_origin then
- local size = 2*size
- local origin = o_cache[size]
- origin = copy_list(origin)
- if getid(parent) == vlist_code then
- setfield(origin,"shift",-shift)
- info = linked_nodes(current,new_kern(-size),origin,new_kern(-size-dp),info)
+ -- we need to trigger the right mode (else sometimes no whatits)
+ local info = setlink(
+ this and copy_list(this) or nil,
+ new_rule(linewidth,ht,dp),
+ new_rule(wd-size,-dp+linewidth,dp),
+ new_rule(linewidth,ht,dp),
+ new_kern(-wd+linewidth),
+ new_rule(wd-size,ht,-ht+linewidth),
+ baseskip,
+ baseskip and baseline or nil
+ )
+ setlisttransparency(info,c_text)
+ info = new_hlist(info)
+ --
+ setattr(info,a_layer,layer)
+ if vertical then
+ if shift == 0 then
+ info = setlink(current,dp ~= 0 and new_kern(-dp) or nil,info)
+ elseif trace_origin then
+ local size = 2*size
+ local origin = o_cache[size]
+ origin = copy_list(origin)
+ if getid(parent) == vlist_code then
+ setshift(origin,-shift)
+ info = setlink(current,new_kern(-size),origin,new_kern(-size-dp),info)
+ else
+ -- todo .. i need an example
+ info = setlink(current,dp ~= 0 and new_kern(-dp) or nil,info)
+ end
+ setshift(current,0)
else
- -- todo .. i need an example
- info = linked_nodes(current,dp ~= 0 and new_kern(-dp) or nil,info)
+ info = setlink(current,new_dp ~= 0 and new_kern(-dp) or nil,info)
+ setshift(current,0)
end
- setfield(current,"shift",0)
+ info = new_vlist(info,wd,ht,dp,shift)
else
- info = linked_nodes(current,new_dp ~= 0 and new_kern(-dp) or nil,info)
- setfield(current,"shift",0)
+ if shift == 0 then
+ info = setlink(current,new_kern(-wd),info)
+ elseif trace_origin then
+ local size = 2*size
+ local origin = o_cache[size]
+ origin = copy_list(origin)
+ if getid(parent) == vlist_code then
+ info = setlink(current,new_kern(-wd-size-shift),origin,new_kern(-size+shift),info)
+ else
+ setshift(origin,-shift)
+ info = setlink(current,new_kern(-wd-size),origin,new_kern(-size),info)
+ end
+ setshift(current,0)
+ else
+ info = setlink(current,new_kern(-wd),info)
+ setshift(current,0)
+ end
+ info = new_hlist(info,wd,ht,dp,shift)
end
- info = new_vlist(info,wd,ht,dp,shift)
- else
- if shift == 0 then
- info = linked_nodes(current,new_kern(-wd),info)
- elseif trace_origin then
- local size = 2*size
- local origin = o_cache[size]
- origin = copy_list(origin)
- if getid(parent) == vlist_code then
- info = linked_nodes(current,new_kern(-wd-size-shift),origin,new_kern(-size+shift),info)
+ if next then
+ setlink(info,next)
+ end
+ if prev then
+ if getid(prev) == gluespec_code then
+ report_visualize("ignoring invalid prev")
+ -- weird, how can this happen, an inline glue-spec, probably math
else
- setfield(origin,"shift",-shift)
- info = linked_nodes(current,new_kern(-wd-size),origin,new_kern(-size),info)
+ setlink(prev,info)
end
- setfield(current,"shift",0)
+ end
+ if head == current then
+ return info, info
else
- info = linked_nodes(current,new_kern(-wd),info)
- setfield(current,"shift",0)
+ return head, info
end
- info = new_hlist(info,wd,ht,dp,shift)
- end
- if next then
- setlink(info,next)
+ else
+ return head, current
end
- if prev then
- if getid(prev) == gluespec_code then
- report_visualize("ignoring invalid prev")
- -- weird, how can this happen, an inline glue-spec, probably math
+ end
+
+end
+
+local ruledglyph do
+
+ ruledglyph = function(head,current,previous) -- wrong for vertical glyphs
+ local wd = getwidth(current)
+ -- local wd = chardata[getfont(current)][getchar(current)].width
+ if wd ~= 0 then
+ local wd, ht, dp = getwhd(current)
+ -- local dir = getdir(current)
+ -- if dir == "LTL" or dir = "RTT" then
+ -- wd, ht, dp = ht + dp, wd, 0
+ -- end
+ local next = getnext(current)
+ local prev = previous
+ setboth(current)
+ local linewidth = emwidth/(2*fraction)
+ local baseline
+ -- if dp ~= 0 and ht ~= 0 then
+ if (dp >= 0 and ht >= 0) or (dp <= 0 and ht <= 0) then
+ baseline = new_rule(wd-2*linewidth,linewidth,0)
+ end
+ local doublelinewidth = 2*linewidth
+ -- could be a pdf rule (or a user rule now)
+ local info = setlink(
+ new_rule(linewidth,ht,dp),
+ new_rule(wd-doublelinewidth,-dp+linewidth,dp),
+ new_rule(linewidth,ht,dp),
+ new_kern(-wd+linewidth),
+ new_rule(wd-doublelinewidth,ht,-ht+linewidth),
+ new_kern(-wd+doublelinewidth),
+ baseline
+ )
+ local char = chardata[getfont(current)][getchar(current)]
+ if char and type(char.unicode) == "table" then -- hackery test
+ setlistcolor(info,c_ligature)
+ setlisttransparency(info,c_ligature_d)
else
+ setlistcolor(info,c_glyph)
+ setlisttransparency(info,c_glyph_d)
+ end
+ info = new_hlist(info)
+ setattr(info,a_layer,l_glyph)
+ local info = setlink(current,new_kern(-wd),info)
+ info = hpack_nodes(info)
+ setwidth(info,wd)
+ if next then
+ setlink(info,next)
+ end
+ if prev then
setlink(prev,info)
end
- end
- if head == current then
- return info, info
+ if head == current then
+ return info, info
+ else
+ return head, info
+ end
else
- return head, info
+ return head, current
end
- else
- return head, current
end
+
end
-local function ruledglyph(head,current,previous) -- wrong for vertical glyphs
- local wd = getfield(current,"width")
- -- local wd = chardata[getfont(current)][getchar(current)].width
- if wd ~= 0 then
- local wd, ht, dp = getwhd(current)
--- local dir = getfield(current,"dir")
--- if dir == "LTL" or dir = "RTT" then
--- wd, ht, dp = ht + dp, wd, 0
--- end
- local next = getnext(current)
- local prev = previous
- setboth(current)
- local linewidth = emwidth/(2*fraction)
- local baseline
- -- if dp ~= 0 and ht ~= 0 then
- if (dp >= 0 and ht >= 0) or (dp <= 0 and ht <= 0) then
- baseline = new_rule(wd-2*linewidth,linewidth,0)
- end
- local doublelinewidth = 2*linewidth
- -- could be a pdf rule (or a user rule now)
- local info = linked_nodes(
- new_rule(linewidth,ht,dp),
- new_rule(wd-doublelinewidth,-dp+linewidth,dp),
- new_rule(linewidth,ht,dp),
- new_kern(-wd+linewidth),
- new_rule(wd-doublelinewidth,ht,-ht+linewidth),
- new_kern(-wd+doublelinewidth),
- baseline
- )
- local char = chardata[getfont(current)][getchar(current)]
- if char and type(char.unicode) == "table" then -- hackery test
- setlistcolor(info,c_ligature)
- setlisttransparency(info,c_ligature_d)
+local ruledglue do
+
+ local g_cache_v = caches["vglue"]
+ local g_cache_h = caches["hglue"]
+
+ local tags = {
+ -- userskip = "US",
+ lineskip = "LS",
+ baselineskip = "BS",
+ parskip = "PS",
+ abovedisplayskip = "DA",
+ belowdisplayskip = "DB",
+ abovedisplayshortskip = "SA",
+ belowdisplayshortskip = "SB",
+ leftskip = "LS",
+ rightskip = "RS",
+ topskip = "TS",
+ splittopskip = "ST",
+ tabskip = "AS",
+ spaceskip = "SS",
+ xspaceskip = "XS",
+ parfillskip = "PF",
+ thinmuskip = "MS",
+ medmuskip = "MM",
+ thickmuskip = "ML",
+ leaders = "NL",
+ cleaders = "CL",
+ xleaders = "XL",
+ gleaders = "GL",
+ -- true = "VS",
+ -- false = "HS",
+ }
+
+ -- we sometimes pass previous as we can have issues in math (not watertight for all)
+
+ ruledglue = function(head,current,vertical,parent)
+ local subtype = getsubtype(current)
+ local width = effectiveglue(current,parent)
+ local amount = formatters["%s:%0.3f"](tags[subtype] or (vertical and "VS") or "HS",width*pt_factor)
+ local info = (vertical and g_cache_v or g_cache_h)[amount]
+ if info then
+ -- print("glue hit")
else
- setlistcolor(info,c_glyph)
- setlisttransparency(info,c_glyph_d)
- end
- info = new_hlist(info)
- setattr(info,a_layer,l_glyph)
- local info = linked_nodes(current,new_kern(-wd),info)
- info = hpack_nodes(info)
- setfield(info,"width",wd)
- if next then
- setlink(info,next)
- end
- if prev then
- setlink(prev,info)
+ if subtype == space_code or subtype == xspace_code then -- not yet all space
+ info = sometext(amount,l_glue,c_space)
+ elseif subtype == leftskip_code or subtype == rightskip_code then
+ info = sometext(amount,l_glue,c_skip_a)
+ elseif subtype == userskip_code then
+ if width > 0 then
+ info = sometext(amount,l_glue,c_positive)
+ elseif width < 0 then
+ info = sometext(amount,l_glue,c_negative)
+ else
+ info = sometext(amount,l_glue,c_zero)
+ end
+ else
+ info = sometext(amount,l_glue,c_skip_b)
+ end
+ (vertical and g_cache_v or g_cache_h)[amount] = info
end
- if head == current then
- return info, info
- else
- return head, info
+ info = copy_list(info)
+ if vertical then
+ info = vpack_nodes(info)
end
- else
- return head, current
+ head, current = insert_node_before(head,current,info)
+ return head, getnext(current)
end
+
end
-local g_cache_v = { }
-local g_cache_h = { }
-
-local tags = {
- -- userskip = "US",
- lineskip = "LS",
- baselineskip = "BS",
- parskip = "PS",
- abovedisplayskip = "DA",
- belowdisplayskip = "DB",
- abovedisplayshortskip = "SA",
- belowdisplayshortskip = "SB",
- leftskip = "LS",
- rightskip = "RS",
- topskip = "TS",
- splittopskip = "ST",
- tabskip = "AS",
- spaceskip = "SS",
- xspaceskip = "XS",
- parfillskip = "PF",
- thinmuskip = "MS",
- medmuskip = "MM",
- thickmuskip = "ML",
- leaders = "NL",
- cleaders = "CL",
- xleaders = "XL",
- gleaders = "GL",
- -- true = "VS",
- -- false = "HS",
-}
+local ruledkern do
--- we sometimes pass previous as we can have issues in math (not watertight for all)
+ local k_cache_v = caches["vkern"]
+ local k_cache_h = caches["hkern"]
-local function ruledglue(head,current,vertical,parent)
- local subtype = getsubtype(current)
- local width = effectiveglue(current,parent)
- local amount = formatters["%s:%0.3f"](tags[subtype] or (vertical and "VS") or "HS",width*pt_factor)
- local info = (vertical and g_cache_v or g_cache_h)[amount]
- if info then
- -- print("glue hit")
- else
- if subtype == space_code or subtype == xspace_code then -- not yet all space
- info = sometext(amount,l_glue,c_space)
- elseif subtype == leftskip_code or subtype == rightskip_code then
- info = sometext(amount,l_glue,c_skip_a)
- elseif subtype == userskip_code then
- if width > 0 then
- info = sometext(amount,l_glue,c_positive)
- elseif width < 0 then
- info = sometext(amount,l_glue,c_negative)
+ ruledkern = function(head,current,vertical)
+ local kern = getkern(current)
+ local info = (vertical and k_cache_v or k_cache_h)[kern]
+ if info then
+ -- print("kern hit")
+ else
+ local amount = formatters["%s:%0.3f"](vertical and "VK" or "HK",kern*pt_factor)
+ if kern > 0 then
+ info = sometext(amount,l_kern,c_positive)
+ elseif kern < 0 then
+ info = sometext(amount,l_kern,c_negative)
else
- info = sometext(amount,l_glue,c_zero)
+ info = sometext(amount,l_kern,c_zero)
end
- else
- info = sometext(amount,l_glue,c_skip_b)
+ (vertical and k_cache_v or k_cache_h)[kern] = info
end
- (vertical and g_cache_v or g_cache_h)[amount] = info
- end
- info = copy_list(info)
- if vertical then
- info = vpack_nodes(info)
+ info = copy_list(info)
+ if vertical then
+ info = vpack_nodes(info)
+ end
+ head, current = insert_node_before(head,current,info)
+ return head, getnext(current)
end
- head, current = insert_node_before(head,current,info)
- return head, getnext(current)
+
end
-local k_cache_v = { }
-local k_cache_h = { }
+local ruleditalic do
-local function ruledkern(head,current,vertical)
- local kern = getfield(current,"kern")
- local info = (vertical and k_cache_v or k_cache_h)[kern]
- if info then
- -- print("kern hit")
- else
- local amount = formatters["%s:%0.3f"](vertical and "VK" or "HK",kern*pt_factor)
- if kern > 0 then
- info = sometext(amount,l_kern,c_positive)
- elseif kern < 0 then
- info = sometext(amount,l_kern,c_negative)
+ local i_cache = caches["itatalic"]
+
+ ruleditalic = function(head,current)
+ local kern = getkern(current)
+ local info = i_cache[kern]
+ if info then
+ -- print("kern hit")
else
- info = sometext(amount,l_kern,c_zero)
+ local amount = formatters["%s:%0.3f"]("IC",kern*pt_factor)
+ if kern > 0 then
+ info = sometext(amount,l_kern,c_positive)
+ elseif kern < 0 then
+ info = sometext(amount,l_kern,c_negative)
+ else
+ info = sometext(amount,l_kern,c_zero)
+ end
+ i_cache[kern] = info
end
- (vertical and k_cache_v or k_cache_h)[kern] = info
- end
- info = copy_list(info)
- if vertical then
- info = vpack_nodes(info)
+ info = copy_list(info)
+ head, current = insert_node_before(head,current,info)
+ return head, getnext(current)
end
- head, current = insert_node_before(head,current,info)
- return head, getnext(current)
-end
-local i_cache = { }
+end
-local function ruleditalic(head,current)
- local kern = getfield(current,"kern")
- local info = i_cache[kern]
- if info then
- -- print("kern hit")
- else
- local amount = formatters["%s:%0.3f"]("IC",kern*pt_factor)
- if kern > 0 then
- info = sometext(amount,l_kern,c_positive)
- elseif kern < 0 then
- info = sometext(amount,l_kern,c_negative)
- else
- info = sometext(amount,l_kern,c_zero)
+local ruleddiscretionary do
+
+ local d_cache = caches["discretionary"]
+
+ ruleddiscretionary = function(head,current)
+ local d = d_cache[true]
+ if not the_discretionary then
+ local rule = new_rule(4*emwidth/fraction,4*exheight,exheight)
+ local kern = new_kern(-2*emwidth/fraction)
+ setlink(kern,rule)
+ setcolor(rule,c_discretionary_d)
+ settransparency(rule,c_discretionary_d)
+ setattr(rule,a_layer,l_discretionary)
+ d = new_hlist(kern)
+ d_cache[true] = d
end
- i_cache[kern] = info
+ insert_node_after(head,current,copy_list(d))
+ return head, current
end
- info = copy_list(info)
- head, current = insert_node_before(head,current,info)
- return head, getnext(current)
+
end
-local p_cache_v = { }
-local p_cache_h = { }
+local ruledpenalty do
-local function ruledpenalty(head,current,vertical)
- local penalty = getfield(current,"penalty")
- local info = (vertical and p_cache_v or p_cache_h)[penalty]
- if info then
- -- print("penalty hit")
- else
- local amount = formatters["%s:%s"](vertical and "VP" or "HP",penalty)
- if penalty > 0 then
- info = sometext(amount,l_penalty,c_positive)
- elseif penalty < 0 then
- info = sometext(amount,l_penalty,c_negative)
+ local p_cache_v = caches["vpenalty"]
+ local p_cache_h = caches["hpenalty"]
+
+ ruledpenalty = function(head,current,vertical)
+ local penalty = getpenalty(current)
+ local info = (vertical and p_cache_v or p_cache_h)[penalty]
+ if info then
+ -- print("penalty hit")
else
- info = sometext(amount,l_penalty,c_zero)
+ local amount = formatters["%s:%s"](vertical and "VP" or "HP",penalty)
+ if penalty > 0 then
+ info = sometext(amount,l_penalty,c_positive)
+ elseif penalty < 0 then
+ info = sometext(amount,l_penalty,c_negative)
+ else
+ info = sometext(amount,l_penalty,c_zero)
+ end
+ (vertical and p_cache_v or p_cache_h)[penalty] = info
end
- (vertical and p_cache_v or p_cache_h)[penalty] = info
- end
- info = copy_list(info)
- if vertical then
- info = vpack_nodes(info)
- elseif raisepenalties then
- setfield(info,"shift",-65536*4)
+ info = copy_list(info)
+ if vertical then
+ info = vpack_nodes(info)
+ elseif raisepenalties then
+ setshift(info,-65536*4)
+ end
+ head, current = insert_node_before(head,current,info)
+ return head, getnext(current)
end
- head, current = insert_node_before(head,current,info)
- return head, getnext(current)
+
end
local function visualize(head,vertical,forced,parent)
@@ -880,37 +954,39 @@ local function visualize(head,vertical,forced,parent)
if a ~= attr then
prev_trace_fontkern = trace_fontkern
if a == unsetvalue then
- trace_hbox = false
- trace_vbox = false
- trace_vtop = false
- trace_kern = false
- trace_glue = false
- trace_penalty = false
- trace_fontkern = false
- trace_strut = false
- trace_whatsit = false
- trace_glyph = false
- trace_simple = false
- trace_user = false
- trace_math = false
- trace_italic = false
- trace_origin = false
+ trace_hbox = false
+ trace_vbox = false
+ trace_vtop = false
+ trace_kern = false
+ trace_glue = false
+ trace_penalty = false
+ trace_fontkern = false
+ trace_strut = false
+ trace_whatsit = false
+ trace_glyph = false
+ trace_simple = false
+ trace_user = false
+ trace_math = false
+ trace_italic = false
+ trace_origin = false
+ trace_discretionary = false
else -- dead slow:
- trace_hbox = hasbit(a, 1)
- trace_vbox = hasbit(a, 2)
- trace_vtop = hasbit(a, 4)
- trace_kern = hasbit(a, 8)
- trace_glue = hasbit(a, 16)
- trace_penalty = hasbit(a, 32)
- trace_fontkern = hasbit(a, 64)
- trace_strut = hasbit(a, 128)
- trace_whatsit = hasbit(a, 256)
- trace_glyph = hasbit(a, 512)
- trace_simple = hasbit(a, 1024)
- trace_user = hasbit(a, 2048)
- trace_math = hasbit(a, 4096)
- trace_italic = hasbit(a, 8192)
- trace_origin = hasbit(a,16384)
+ trace_hbox = hasbit(a, 1)
+ trace_vbox = hasbit(a, 2)
+ trace_vtop = hasbit(a, 4)
+ trace_kern = hasbit(a, 8)
+ trace_glue = hasbit(a, 16)
+ trace_penalty = hasbit(a, 32)
+ trace_fontkern = hasbit(a, 64)
+ trace_strut = hasbit(a, 128)
+ trace_whatsit = hasbit(a, 256)
+ trace_glyph = hasbit(a, 512)
+ trace_simple = hasbit(a, 1024)
+ trace_user = hasbit(a, 2048)
+ trace_math = hasbit(a, 4096)
+ trace_italic = hasbit(a, 8192)
+ trace_origin = hasbit(a,16384)
+ trace_discretionary = hasbit(a,32768)
end
attr = a
end
@@ -921,6 +997,9 @@ local function visualize(head,vertical,forced,parent)
head, current = ruledglyph(head,current,previous)
end
elseif id == disc_code then
+ if trace_discretionary then
+ head, current = ruleddiscretionary(head,current)
+ end
local pre, post, replace = getdisc(current)
if pre then
pre = visualize(pre,false,a,parent)
@@ -996,46 +1075,21 @@ end
do
- local function freed(cache)
- local n = 0
- for k, v in next, cache do
- flush_node_list(v)
- n = n + 1
+ local function cleanup()
+ for tag, cache in next, caches do
+ for k, v in next, cache do
+ flush_node_list(v)
+ end
end
- if n == 0 then
- return 0, cache
- else
- return n, { }
+ cleanup = function()
+ report_visualize("error, duplicate cleanup")
end
end
- local function cleanup()
- local hf, nw, nb, ng_v, ng_h, np_v, np_h, nk_v, nk_h
- nf, f_cache = freed(f_cache)
- nw, w_cache = freed(w_cache)
- nb, b_cache = freed(b_cache)
- no, o_cache = freed(o_cache)
- ng_v, g_cache_v = freed(g_cache_v)
- ng_h, g_cache_h = freed(g_cache_h)
- np_v, p_cache_v = freed(p_cache_v)
- np_h, p_cache_h = freed(p_cache_h)
- nk_v, k_cache_v = freed(k_cache_v)
- nk_h, k_cache_h = freed(k_cache_h)
- -- report_visualize("cache cleanup: %s fontkerns, %s skips, %s penalties, %s kerns, %s whatsits, %s boxes, %s origins",
- -- nf,ng_v+ng_h,np_v+np_h,nk_v+nk_h,nw,nb,no)
- end
-
local function handler(head)
if usedfont then
starttiming(visualizers)
- -- local l = texgetattribute(a_layer)
- -- local v = texgetattribute(a_visual)
- -- texsetattribute(a_layer,unsetvalue)
- -- texsetattribute(a_visual,unsetvalue)
head = visualize(tonut(head),true)
- -- texsetattribute(a_layer,l)
- -- texsetattribute(a_visual,v)
- -- -- cleanup()
stoptiming(visualizers)
return tonode(head), true
else
diff --git a/tex/context/base/mkiv/trac-vis.mkiv b/tex/context/base/mkiv/trac-vis.mkiv
index a503981f5..894408222 100644
--- a/tex/context/base/mkiv/trac-vis.mkiv
+++ b/tex/context/base/mkiv/trac-vis.mkiv
@@ -39,7 +39,7 @@
\newconstant\c_syst_visualizers_state
\newtoks \t_syst_visualizers_optimize
-\definesystemattribute[visual][public,global] % global ?
+% \definesystemattribute[visual][public,global] % already defined
% no, but can become an option:
%
diff --git a/tex/context/base/mkiv/typo-brk.lua b/tex/context/base/mkiv/typo-brk.lua
index 749c25a33..84eff0654 100644
--- a/tex/context/base/mkiv/typo-brk.lua
+++ b/tex/context/base/mkiv/typo-brk.lua
@@ -32,11 +32,15 @@ local getsubtype = nuts.getsubtype
local getfont = nuts.getfont
local getid = nuts.getid
local getfield = nuts.getfield
-local getattr = nuts.getattr
+----- getattr = nuts.getattr
+local getattrlist = nuts.getattrlist
+local takeattr = nuts.takeattr
+local getlang = nuts.getlang
local isglyph = nuts.isglyph
local setfield = nuts.setfield
local setattr = nuts.setattr
+local setattrlist = nuts.setattrlist
local setlink = nuts.setlink
local setchar = nuts.setchar
local setdisc = nuts.setdisc
@@ -59,7 +63,7 @@ local texsetattribute = tex.setattribute
local unsetvalue = attributes.unsetvalue
local nodepool = nuts.pool
-local tasks = nodes.tasks
+local enableaction = nodes.tasks.enableaction
local v_reset = interfaces.variables.reset
local v_yes = interfaces.variables.yes
@@ -109,19 +113,21 @@ end
-- todo: use boundaries
-local function withattribute(n,a)
- setfield(n,"attr",a)
- return n
-end
-
local function insert_break(head,start,stop,before,after,kern)
- local a = getfield(start,"attr")
if not kern then
- insert_node_before(head,start,withattribute(new_penalty(before),a))
- insert_node_before(head,start,withattribute(new_glue(0),a))
+ local p = new_penalty(before)
+ local g = new_glue()
+ setattrlist(p,start)
+ setattrlist(g,start)
+ insert_node_before(head,start,p)
+ insert_node_before(head,start,g)
end
- insert_node_after(head,stop,withattribute(new_glue(0),a))
- insert_node_after(head,stop,withattribute(new_penalty(after),a))
+ local p = new_penalty(after)
+ local g = new_glue()
+ setattrlist(p,start)
+ setattrlist(g,start)
+ insert_node_after(head,stop,g)
+ insert_node_after(head,stop,p)
end
methods[1] = function(head,start,stop,settings,kern)
@@ -142,14 +148,8 @@ methods[6] = function(head,start,stop,settings,kern)
local l = new_wordboundary()
local d = new_disc()
local r = new_wordboundary()
- local a = getfield(start,"attr")
- -- setfield(l,"attr",a)
- setfield(d,"attr",a) -- otherwise basemode is forces and we crash
- -- setfield(r,"attr",a)
- setlink(p,l)
- setlink(l,d)
- setlink(d,r)
- setlink(r,n)
+ setattrlist(d,start) -- otherwise basemode is forced and we crash
+ setlink(p,l,d,r,n)
if start == stop then
setboth(start)
setdisc(d,start,nil,copy_node(start))
@@ -167,16 +167,14 @@ end
methods[2] = function(head,start) -- ( => (-
local p, n = getboth(start)
if p and n then
- local tmp
- head, start, tmp = remove_node(head,start)
- head, start = insert_node_before(head,start,new_disc())
- setfield(start,"attr",getfield(tmp,"attr"))
- setfield(start,"replace",tmp)
- local tmp = copy_node(tmp)
- local hyphen = copy_node(tmp)
- setchar(hyphen,languages.prehyphenchar(getfield(tmp,"lang")))
- setlink(tmp,hyphen)
- setfield(start,"post",tmp)
+ local replace
+ head, start, replace = remove_node(head,start)
+ local post = copy_node(replace)
+ local hyphen = copy_node(post)
+ setchar(hyphen,languages.prehyphenchar(getlang(post)))
+ setlink(post,hyphen)
+ head, start = insert_node_before(head,start,new_disc(nil,post,replace))
+ setattrlist(start,replace)
insert_break(head,start,start,10000,10000)
end
return head, start
@@ -185,16 +183,14 @@ end
methods[3] = function(head,start) -- ) => -)
local p, n = getboth(start)
if p and n then
- local tmp
- head, start, tmp = remove_node(head,start)
- head, start = insert_node_before(head,start,new_disc())
- setfield(start,"attr",getfield(tmp,"attr"))
- setfield(start,"replace",tmp)
- local tmp = copy_node(tmp)
- local hyphen = copy_node(tmp)
- setchar(hyphen,languages.prehyphenchar(getfield(tmp,"lang")))
- setlink(hyphen,tmp)
- setfield(start,"pre",hyphen)
+ local replace
+ head, start, replace = remove_node(head,start)
+ local pre = copy_node(replace)
+ local hyphen = copy_node(pre)
+ setchar(hyphen,languages.prehyphenchar(getlang(pre)))
+ setlink(hyphen,pre)
+ head, start = insert_node_before(head,start,new_disc(hyphen,nil,replace)) -- so not pre !
+ setattrlist(start,tmp)
insert_break(head,start,start,10000,10000)
end
return head, start
@@ -206,7 +202,7 @@ methods[4] = function(head,start) -- - => - - -
local tmp
head, start, tmp = remove_node(head,start)
head, start = insert_node_before(head,start,new_disc())
- setfield(start,"attr",getfield(tmp,"attr"))
+ setattrlist(start,tmp)
setdisc(start,copy_node(tmp),copy_node(tmp),tmp)
insert_break(head,start,start,10000,10000)
end
@@ -218,11 +214,11 @@ methods[5] = function(head,start,stop,settings) -- x => p q r
if p and n then
local tmp
head, start, tmp = remove_node(head,start)
- head, start = insert_node_before(head,start,new_disc())
- local attr = getfield(tmp,"attr")
- local font = getfont(tmp)
- local left = settings.left
- local right = settings.right
+ head, start = insert_node_before(head,start,new_disc())
+ local attr = getattrlist(tmp)
+ local font = getfont(tmp)
+ local left = settings.left
+ local right = settings.right
local middle = settings.middle
if left then
left = tonodes(tostring(left),font,attr)
@@ -234,7 +230,7 @@ methods[5] = function(head,start,stop,settings) -- x => p q r
middle = tonodes(tostring(middle),font,attr)
end
setdisc(start,left,right,middle)
- setfield(start,"attr",attr) -- todo: critical only -- just a copy will do
+ setattrlist(start,attr)
flush_node(tmp)
insert_break(head,start,start,10000,10000)
end
@@ -254,7 +250,8 @@ function breakpoints.handler(head)
while current do
local char, id = isglyph(current)
if char then
- local a = getattr(current,a_breakpoints)
+ -- local a = getattr(current,a_breakpoints)
+ local a = takeattr(current,a_breakpoints)
if a and a > 0 then
if a ~= attr then
local data = mapping[a]
@@ -268,10 +265,10 @@ function breakpoints.handler(head)
if map then
local cmap = map[char]
if cmap then
- setattr(current,a_breakpoints,unsetvalue) -- should not be needed
+ -- setattr(current,a_breakpoints,unsetvalue) -- should not be needed
-- for now we collect but when found ok we can move the handler here
-- although it saves nothing in terms of performance
- local lang = getfield(current,"lang")
+ local lang = getlang(current)
local smap = lang and lang >= 0 and lang < 0x7FFF and (cmap[numbers[lang]] or cmap[""])
if smap then
local skip = smap.skip
@@ -328,7 +325,7 @@ function breakpoints.handler(head)
local stop = data[2]
local cmap = data[3]
local smap = data[4]
--- local lang = getfield(start,"lang")
+-- local lang = getlang(start)
-- -- we do a sanity check for language
-- local smap = lang and lang >= 0 and lang < 0x7FFF and (cmap[numbers[lang]] or cmap[""])
-- if smap then
@@ -450,7 +447,7 @@ function breakpoints.set(n)
if trace_breakpoints then
report_breakpoints("enabling breakpoints handler")
end
- tasks.enableaction("processors","typesetters.breakpoints.handler")
+ enableaction("processors","typesetters.breakpoints.handler")
end
n = n.number
end
@@ -458,10 +455,6 @@ function breakpoints.set(n)
texsetattribute(a_breakpoints,n)
end
--- function breakpoints.enable()
--- tasks.enableaction("processors","typesetters.breakpoints.handler")
--- end
-
-- interface
implement {
diff --git a/tex/context/base/mkiv/typo-cap.lua b/tex/context/base/mkiv/typo-cap.lua
index 972c5ea20..6bf4669df 100644
--- a/tex/context/base/mkiv/typo-cap.lua
+++ b/tex/context/base/mkiv/typo-cap.lua
@@ -25,7 +25,8 @@ local getfield = nuts.getfield
local getnext = nuts.getnext
local getprev = nuts.getprev
local getid = nuts.getid
-local getattr = nuts.getattr
+----- getattr = nuts.getattr
+local takeattr = nuts.takeattr
local getfont = nuts.getfont
local getsubtype = nuts.getsubtype
local getchar = nuts.getchar
@@ -34,11 +35,13 @@ local getdisc = nuts.getdisc
local setfield = nuts.setfield
local setattr = nuts.setattr
local setchar = nuts.setchar
+local setfont = nuts.setfont
local copy_node = nuts.copy
local end_of_math = nuts.end_of_math
local traverse_id = nuts.traverse_id
local insert_after = nuts.insert_after
+local find_attribute = nuts.find_attribute
local nodecodes = nodes.nodecodes
local skipcodes = nodes.skipcodes
@@ -51,7 +54,7 @@ local math_code = nodecodes.math
local kerning_code = kerncodes.kerning
-local tasks = nodes.tasks
+local enableaction = nodes.tasks.enableaction
local newkern = nuts.pool.kern
@@ -214,7 +217,7 @@ end
-- elseif dc == char then
-- local lfa = lastfont[n]
-- if lfa then
--- setfield(first,"font",lfa)
+-- setfont(first,lfa)
-- return start, true, true
-- else
-- return start, false, true
@@ -237,7 +240,7 @@ local function mixed(start,attr,lastfont,n,count,where,first)
elseif dc == char then
local lfa = lastfont[n]
if lfa then
- setfield(used,"font",lfa)
+ setfont(used,lfa)
return start, true, true
else
return start, false, true
@@ -274,7 +277,7 @@ local function Capital(start,attr,lastfont,n,count,where,first,once) -- 3
if lfa then
local dc = uccodes[getchar(used)]
if dc then
- setfield(used,"font",lfa)
+ setfont(used,lfa)
end
end
end
@@ -335,17 +338,18 @@ register(variables.cap, variables.capital) -- clone
register(variables.Cap, variables.Capital) -- clone
function cases.handler(head) -- not real fast but also not used on much data
+ local start = tonut(head)
local lastfont = { }
local lastattr = nil
local done = false
- local start = tonut(head)
local count = 0
local previd = nil
local prev = nil
while start do -- while because start can jump ahead
local id = getid(start)
if id == glyph_code then
- local attr = getattr(start,a_cases)
+ -- local attr = getattr(start,a_cases)
+ local attr = takeattr(start,a_cases)
if attr and attr > 0 and not blocked[attr] then
if attr ~= lastattr then
lastattr = attr
@@ -353,7 +357,7 @@ function cases.handler(head) -- not real fast but also not used on much data
else
count = count + 1
end
- setattr(start,a_cases,unsetvalue)
+ -- setattr(start,a_cases,unsetvalue) -- not needed
local n, id, m = get(attr)
if lastfont[n] == nil then
lastfont[n] = id
@@ -372,13 +376,14 @@ function cases.handler(head) -- not real fast but also not used on much data
end
end
elseif id == disc_code then
- local attr = getattr(start,a_cases)
+ -- local attr = getattr(start,a_cases)
+ local attr = takeattr(start,a_cases)
if attr and attr > 0 and not blocked[attr] then
if attr ~= lastattr then
lastattr = attr
count = 0
end
- setattr(start,a_cases,unsetvalue)
+ -- setattr(start,a_cases,unsetvalue) -- not needed
local n, id, m = get(attr)
if lastfont[n] == nil then
lastfont[n] = id
@@ -390,6 +395,7 @@ function cases.handler(head) -- not real fast but also not used on much data
local cnt = count
for g in traverse_id(glyph_code,replace) do
cnt = cnt + 1
+ takeattr(g,a_cases)
-- setattr(g,a_cases,unsetvalue)
local _, _, quit = action(start,attr,lastfont,n,cnt,"replace",g)
if quit then break end
@@ -399,6 +405,7 @@ function cases.handler(head) -- not real fast but also not used on much data
local cnt = count
for g in traverse_id(glyph_code,pre) do
cnt = cnt + 1
+ takeattr(g,a_cases)
-- setattr(g,a_cases,unsetvalue)
local _, _, quit = action(start,attr,lastfont,n,cnt,"pre",g)
if quit then break end
@@ -408,6 +415,7 @@ function cases.handler(head) -- not real fast but also not used on much data
local cnt = count
for g in traverse_id(glyph_code,post) do
cnt = cnt + 1
+ takeattr(g,a_cases)
-- setattr(g,a_cases,unsetvalue)
local _, _, quit = action(start,attr,lastfont,n,cnt,"post",g)
if quit then break end
@@ -420,7 +428,7 @@ function cases.handler(head) -- not real fast but also not used on much data
start = end_of_math(start)
count = 0
elseif prev_id == kern_code and getsubtype(prev) == kerning_code then
- -- still inside a word ...nomally kerns are added later
+ -- still inside a word ...normally kerns are added later
else
count = 0
end
@@ -433,6 +441,120 @@ function cases.handler(head) -- not real fast but also not used on much data
return head, done
end
+-- function cases.handler(head) -- not real fast but also not used on much data
+-- local attr, start = find_attribute(tonut(head),a_cases)
+-- if not start then
+-- return head, false
+-- end
+-- local lastfont = { }
+-- local lastattr = nil
+-- local done = false
+-- local count = 0
+-- local previd = nil
+-- local prev = nil
+-- while start do
+-- while start do -- while because start can jump ahead
+-- local id = getid(start)
+-- if id == glyph_code then
+-- -- local attr = getattr(start,a_cases)
+-- local attr = takeattr(start,a_cases)
+-- if attr and attr > 0 and not blocked[attr] then
+-- if attr ~= lastattr then
+-- lastattr = attr
+-- count = 1
+-- else
+-- count = count + 1
+-- end
+-- -- setattr(start,a_cases,unsetvalue) -- not needed
+-- local n, id, m = get(attr)
+-- if lastfont[n] == nil then
+-- lastfont[n] = id
+-- end
+-- local action = actions[n] -- map back to low number
+-- if action then
+-- start, ok = action(start,attr,lastfont,n,count)
+-- if ok then
+-- done = true
+-- end
+-- if trace_casing then
+-- report_casing("case trigger %a, instance %a, fontid %a, result %a",n,m,id,ok)
+-- end
+-- elseif trace_casing then
+-- report_casing("unknown case trigger %a",n)
+-- end
+-- end
+-- elseif id == disc_code then
+-- -- local attr = getattr(start,a_cases)
+-- local attr = takeattr(start,a_cases)
+-- if attr and attr > 0 and not blocked[attr] then
+-- if attr ~= lastattr then
+-- lastattr = attr
+-- count = 0
+-- end
+-- -- setattr(start,a_cases,unsetvalue) -- not needed
+-- local n, id, m = get(attr)
+-- if lastfont[n] == nil then
+-- lastfont[n] = id
+-- end
+-- local action = actions[n] -- map back to low number
+-- if action then
+-- local pre, post, replace = getdisc(start)
+-- if replace then
+-- local cnt = count
+-- for g in traverse_id(glyph_code,replace) do
+-- cnt = cnt + 1
+-- takeattr(g,a_cases)
+-- -- setattr(g,a_cases,unsetvalue)
+-- local _, _, quit = action(start,attr,lastfont,n,cnt,"replace",g)
+-- if quit then break end
+-- end
+-- end
+-- if pre then
+-- local cnt = count
+-- for g in traverse_id(glyph_code,pre) do
+-- cnt = cnt + 1
+-- takeattr(g,a_cases)
+-- -- setattr(g,a_cases,unsetvalue)
+-- local _, _, quit = action(start,attr,lastfont,n,cnt,"pre",g)
+-- if quit then break end
+-- end
+-- end
+-- if post then
+-- local cnt = count
+-- for g in traverse_id(glyph_code,post) do
+-- cnt = cnt + 1
+-- takeattr(g,a_cases)
+-- -- setattr(g,a_cases,unsetvalue)
+-- local _, _, quit = action(start,attr,lastfont,n,cnt,"post",g)
+-- if quit then break end
+-- end
+-- end
+-- end
+-- count = count + 1
+-- end
+-- elseif id == math_code then
+-- start = end_of_math(start)
+-- count = 0
+-- elseif prev_id == kern_code and getsubtype(prev) == kerning_code then
+-- -- still inside a word ...normally kerns are added later
+-- else
+-- count = 0
+-- start = getnext(start)
+-- break
+-- end
+-- if start then
+-- prev = start
+-- previd = id
+-- start = getnext(start)
+-- end
+-- end
+-- if start then
+-- attr, start = find_attribute(start,a_cases)
+-- end
+-- end
+-- return head, done
+-- end
+
-- function cases.handler(head) -- let's assume head doesn't change ... no reason
-- local done = false
-- local lastfont = { }
@@ -461,7 +583,7 @@ function cases.set(n,id)
n = registered[n] or tonumber(n)
if n then
if not enabled then
- tasks.enableaction("processors","typesetters.cases.handler")
+ enableaction("processors","typesetters.cases.handler")
if trace_casing then
report_casing("enabling case handler")
end
diff --git a/tex/context/base/mkiv/typo-cap.mkiv b/tex/context/base/mkiv/typo-cap.mkiv
index 114532e4e..96f3e28d6 100644
--- a/tex/context/base/mkiv/typo-cap.mkiv
+++ b/tex/context/base/mkiv/typo-cap.mkiv
@@ -20,7 +20,7 @@
\registerctxluafile{typo-cap}{1.001}
-\definesystemattribute[case][public]
+% \definesystemattribute[case][public] % already predefined
%D \macros
%D {setupcapitals}
diff --git a/tex/context/base/mkiv/typo-cln.lua b/tex/context/base/mkiv/typo-cln.lua
index bc11f944c..53452f838 100644
--- a/tex/context/base/mkiv/typo-cln.lua
+++ b/tex/context/base/mkiv/typo-cln.lua
@@ -24,7 +24,8 @@ local cleaners = typesetters.cleaners
local variables = interfaces.variables
local nodecodes = nodes.nodecodes
-local tasks = nodes.tasks
+
+local enableaction = nodes.tasks.enableaction
local texsetattribute = tex.setattribute
@@ -91,7 +92,7 @@ function cleaners.set(n)
texsetattribute(a_cleaner,unsetvalue)
else
if not enabled then
- tasks.enableaction("processors","typesetters.cleaners.handler")
+ enableaction("processors","typesetters.cleaners.handler")
if trace_cleaners then
report_cleaners("enabling cleaners")
end
diff --git a/tex/context/base/mkiv/typo-dha.lua b/tex/context/base/mkiv/typo-dha.lua
index bdba20878..a32f72e46 100644
--- a/tex/context/base/mkiv/typo-dha.lua
+++ b/tex/context/base/mkiv/typo-dha.lua
@@ -58,6 +58,7 @@ local getlist = nuts.getlist
local getfield = nuts.getfield
local getattr = nuts.getattr
local getprop = nuts.getprop
+local getdir = nuts.getdir
local isglyph = nuts.isglyph -- or ischar
local setfield = nuts.setfield
@@ -312,7 +313,7 @@ local function process(start)
elseif id == kern_code then
setprop(current,"direction",'k')
elseif id == dir_code then
- local dir = getfield(current,"dir")
+ local dir = getdir(current)
if dir == "+TRT" then
autodir = -1
elseif dir == "+TLT" then
@@ -329,7 +330,7 @@ local function process(start)
textdir = autodir
setprop(current,"direction",true)
elseif id == localpar_code then
- local dir = getfield(current,"dir")
+ local dir = getdir(current)
if dir == 'TRT' then
autodir = -1
elseif dir == 'TLT' then
diff --git a/tex/context/base/mkiv/typo-dig.lua b/tex/context/base/mkiv/typo-dig.lua
index 076761ad9..3d60131c7 100644
--- a/tex/context/base/mkiv/typo-dig.lua
+++ b/tex/context/base/mkiv/typo-dig.lua
@@ -28,13 +28,13 @@ local getprev = nuts.getprev
local getfont = nuts.getfont
local getchar = nuts.getchar
local getid = nuts.getid
+local getwidth = nuts.getwidth
local getfield = nuts.getfield
-local getattr = nuts.getattr
+local takeattr = nuts.takeattr
local setlink = nuts.setlink
local setnext = nuts.setnext
local setprev = nuts.setprev
-local setattr = nuts.setattr
local hpack_node = nuts.hpack
local traverse_id = nuts.traverse_id
@@ -48,7 +48,7 @@ local nodecodes = nodes.nodecodes
local glyph_code = nodecodes.glyph
local nodepool = nuts.pool
-local tasks = nodes.tasks
+local enableaction = nodes.tasks.enableaction
local new_glue = nodepool.glue
@@ -104,7 +104,7 @@ actions[1] = function(head,start,attr)
local char = getchar(start)
local unic = chardata[font][char].unicode or char
if charbase[unic].category == "nd" then -- ignore unic tables
- local oldwidth = getfield(start,"width")
+ local oldwidth = getwidth(start)
local newwidth = getdigitwidth(font)
if newwidth ~= oldwidth then
if trace_digits then
@@ -123,9 +123,8 @@ function digits.handler(head)
local done, current, ok = false, head, false
while current do
if getid(current) == glyph_code then
- local attr = getattr(current,a_digits)
+ local attr = takeattr(current,a_digits)
if attr and attr > 0 then
- setattr(current,a_digits,unsetvalue)
local action = actions[attr%100] -- map back to low number
if action then
head, current, ok = action(head,current,attr)
@@ -151,7 +150,7 @@ function digits.set(n) -- number or 'reset'
n = tonumber(n)
if n then
if not enabled then
- tasks.enableaction("processors","typesetters.digits.handler")
+ enableaction("processors","typesetters.digits.handler")
if trace_digits then
report_digits("enabling digit handler")
end
diff --git a/tex/context/base/mkiv/typo-dir.lua b/tex/context/base/mkiv/typo-dir.lua
index 4422a15de..5ecf77a1f 100644
--- a/tex/context/base/mkiv/typo-dir.lua
+++ b/tex/context/base/mkiv/typo-dir.lua
@@ -44,7 +44,7 @@ local hasbit = number.hasbit
local texsetattribute = tex.setattribute
local unsetvalue = attributes.unsetvalue
-local tasks = nodes.tasks
+local enableaction = nodes.tasks.enableaction
local tracers = nodes.tracers
local setcolor = tracers.colors.set
local resetcolor = tracers.colors.reset
@@ -180,16 +180,12 @@ statistics.register("text directions", function()
end
end)
--- function directions.enable()
--- tasks.enableaction("processors","directions.handler")
--- end
-
function directions.set(n) -- todo: names and numbers
if not enabled then
if trace_textdirections then
report_textdirections("enabling directions handler")
end
- tasks.enableaction("processors","typesetters.directions.handler")
+ enableaction("processors","typesetters.directions.handler")
enabled = true
end
if not n or n == 0 then
diff --git a/tex/context/base/mkiv/typo-drp.lua b/tex/context/base/mkiv/typo-drp.lua
index 0683a3472..e27ad75f3 100644
--- a/tex/context/base/mkiv/typo-drp.lua
+++ b/tex/context/base/mkiv/typo-drp.lua
@@ -22,7 +22,10 @@ local initials = typesetters.paragraphs or { }
typesetters.initials = initials or { }
local nodes = nodes
+
local tasks = nodes.tasks
+local enableaction = tasks.enableaction
+local disableaction = tasks.disableaction
local nuts = nodes.nuts
local tonut = nuts.tonut
@@ -42,8 +45,11 @@ local setattr = nuts.setattr
local setlink = nuts.setlink
local setprev = nuts.setprev
local setnext = nuts.setnext
+local setfont = nuts.setfont
local setchar = nuts.setchar
local setwhd = nuts.setwhd
+local setkern = nuts.setkern
+local setoffsets = nuts.setoffsets
local hpack_nodes = nuts.hpack
@@ -91,7 +97,7 @@ local settings = nil
function initials.set(specification)
settings = specification or { }
settings.enabled = true
- tasks.enableaction("processors","typesetters.initials.handler")
+ enableaction("processors","typesetters.initials.handler")
if trace_initials then
report_initials("enabling initials")
end
@@ -250,11 +256,11 @@ actions[v_default] = function(head,setting)
while true do
local id = getid(current)
if id == kern_code then
- setfield(current,"kern",0)
+ setkern(current,0)
elseif id == glyph_code then
local next = getnext(current)
if font then
- setfield(current,"font",font)
+ setfont(current,font)
end
if dynamic > 0 then
setattr(current,0,dynamic)
@@ -316,8 +322,7 @@ actions[v_default] = function(head,setting)
--
local hoffset = width + hoffset + distance + (indent and parindent or 0)
for current in traverse_id(glyph_code,first) do
- setfield(current,"xoffset",- hoffset )
- setfield(current,"yoffset",- voffset) -- no longer - height here
+ setoffsets(current,-hoffset,-voffset) -- no longer - height here
if current == last then
break
end
@@ -366,7 +371,7 @@ function initials.handler(head)
end
if attr then
-- here as we can process nested boxes first so we need to keep state
- tasks.disableaction("processors","typesetters.initials.handler")
+ disableaction("processors","typesetters.initials.handler")
-- texsetattribute(attribute,unsetvalue)
local alternative = settings.alternative or v_default
local action = actions[alternative] or actions[v_default]
diff --git a/tex/context/base/mkiv/typo-dua.lua b/tex/context/base/mkiv/typo-dua.lua
index 596503dbc..c2f3c2763 100644
--- a/tex/context/base/mkiv/typo-dua.lua
+++ b/tex/context/base/mkiv/typo-dua.lua
@@ -77,10 +77,13 @@ local getlist = nuts.getlist
local getchar = nuts.getchar
local getfield = nuts.getfield
local getprop = nuts.getprop
+local getdir = nuts.getdir
local setfield = nuts.setfield
local setprop = nuts.setprop
local setchar = nuts.setchar
+local setdir = nuts.setdir
+----- setattrlist = nuts.setattrlist
local remove_node = nuts.remove
local insert_node_after = nuts.insert_after
@@ -232,7 +235,7 @@ local function build_list(head) -- todo: store node pointer ... saves loop
list[size] = { char = 0x0020, direction = "ws", original = "ws", level = 0 }
current = getnext(current)
elseif id == dir_code then
- local dir = getfield(current,"dir")
+ local dir = getdir(current)
if dir == "+TLT" then
list[size] = { char = 0x202A, direction = "lre", original = "lre", level = 0 }
elseif dir == "+TRT" then
@@ -324,7 +327,7 @@ end
local function get_baselevel(head,list,size) -- todo: skip if first is object (or pass head and test for localpar)
local id = getid(head)
if id == localpar_code then
- if getfield(head,"dir") == "TRT" then
+ if getdir(head) == "TRT" then
return 1, "TRT", true
else
return 0, "TLT", true
@@ -747,13 +750,13 @@ local function apply_to_list(list,size,head,pardir)
setcolor(current,direction,false,mirror)
end
elseif id == hlist_code or id == vlist_code then
- setfield(current,"dir",pardir) -- is this really needed?
+ setdir(current,pardir) -- is this really needed?
elseif id == glue_code then
if enddir and getsubtype(current) == parfillskip_code then
-- insert the last enddir before \parfillskip glue
local d = new_textdir(enddir)
setprop(d,"directions",true)
- -- setfield(d,"attr",getfield(current,"attr"))
+ -- setattrlist(d,current)
head = insert_node_before(head,current,d)
enddir = false
done = true
@@ -763,7 +766,7 @@ local function apply_to_list(list,size,head,pardir)
-- localpar should always be the 1st node
local d = new_textdir(begindir)
setprop(d,"directions",true)
- -- setfield(d,"attr",getfield(current,"attr"))
+ -- setattrlist(d,current)
head, current = insert_node_after(head,current,d)
begindir = nil
done = true
@@ -772,7 +775,7 @@ local function apply_to_list(list,size,head,pardir)
if begindir then
local d = new_textdir(begindir)
setprop(d,"directions",true)
- -- setfield(d,"attr",getfield(current,"attr"))
+ -- setattrlist(d,current)
head = insert_node_before(head,current,d)
done = true
end
@@ -786,7 +789,7 @@ local function apply_to_list(list,size,head,pardir)
if enddir then
local d = new_textdir(enddir)
setprop(d,"directions",true)
- -- setfield(d,"attr",getfield(current,"attr"))
+ -- setattrlist(d,current)
head, current = insert_node_after(head,current,d)
done = true
end
diff --git a/tex/context/base/mkiv/typo-dub.lua b/tex/context/base/mkiv/typo-dub.lua
index 5a60a11e6..eea743c6d 100644
--- a/tex/context/base/mkiv/typo-dub.lua
+++ b/tex/context/base/mkiv/typo-dub.lua
@@ -66,10 +66,13 @@ local getchar = nuts.getchar
local getattr = nuts.getattr
local getfield = nuts.getfield
local getprop = nuts.getprop
+local getdir = nuts.getdir
local setfield = nuts.setfield
local setprop = nuts.setprop
local setchar = nuts.setchar
+local setdir = nuts.setdir
+local setattrlist = nuts.setattrlist
local remove_node = nuts.remove
local insert_node_after = nuts.insert_after
@@ -281,7 +284,7 @@ local function build_list(head) -- todo: store node pointer ... saves loop
list[size] = { char = 0x0020, direction = "ws", original = "ws", level = 0 }
current = getnext(current)
elseif id == dir_code then
- local dir = getfield(current,"dir")
+ local dir = getdir(current)
if dir == "+TLT" then
list[size] = { char = 0x202A, direction = "lre", original = "lre", level = 0 }
elseif dir == "+TRT" then
@@ -396,7 +399,7 @@ end
local function get_baselevel(head,list,size) -- todo: skip if first is object (or pass head and test for localpar)
local id = getid(head)
if id == localpar_code then
- if getfield(head,"dir") == "TRT" then
+ if getdir(head) == "TRT" then
return 1, "TRT", true
else
return 0, "TLT", true
@@ -894,13 +897,13 @@ local function apply_to_list(list,size,head,pardir)
setcolor(current,direction,false,mirror)
end
elseif id == hlist_code or id == vlist_code then
- setfield(current,"dir",pardir) -- is this really needed?
+ setdir(current,pardir) -- is this really needed?
elseif id == glue_code then
if enddir and getsubtype(current) == parfillskip_code then
-- insert the last enddir before \parfillskip glue
local d = new_textdir(enddir)
setprop(d,"directions",true)
- -- setfield(d,"attr",getfield(current,"attr"))
+ -- setattrlist(d,current)
head = insert_node_before(head,current,d)
enddir = false
done = true
@@ -910,7 +913,7 @@ local function apply_to_list(list,size,head,pardir)
-- localpar should always be the 1st node
local d = new_textdir(begindir)
setprop(d,"directions",true)
- -- setfield(d,"attr",getfield(current,"attr"))
+ -- setattrlist(d,current)
head, current = insert_node_after(head,current,d)
begindir = nil
done = true
@@ -919,7 +922,7 @@ local function apply_to_list(list,size,head,pardir)
if begindir then
local d = new_textdir(begindir)
setprop(d,"directions",true)
- -- setfield(d,"attr",getfield(current,"attr"))
+ -- setattrlist(d,current)
head = insert_node_before(head,current,d)
done = true
end
@@ -933,7 +936,7 @@ local function apply_to_list(list,size,head,pardir)
if enddir then
local d = new_textdir(enddir)
setprop(d,"directions",true)
- -- setfield(d,"attr",getfield(current,"attr"))
+ -- setattrlist(d,current)
head, current = insert_node_after(head,current,d)
done = true
end
diff --git a/tex/context/base/mkiv/typo-duc.lua b/tex/context/base/mkiv/typo-duc.lua
index dfb69bcba..7fd49e54e 100644
--- a/tex/context/base/mkiv/typo-duc.lua
+++ b/tex/context/base/mkiv/typo-duc.lua
@@ -67,10 +67,13 @@ local getlist = nuts.getlist
local getattr = nuts.getattr
local getfield = nuts.getfield
local getprop = nuts.getprop
+local getdir = nuts.getdir
local setfield = nuts.setfield
local setprop = nuts.setprop
local setchar = nuts.setchar
+local setdir = nuts.setdir
+local setattrlist = nuts.setattrlist
local properties = nodes.properties
@@ -288,7 +291,7 @@ local function build_list(head) -- todo: store node pointer ... saves loop
setmetatable(t,mt_space)
current = getnext(current)
elseif id == dir_code then
- local dir = getfield(current,"dir")
+ local dir = getdir(current)
if dir == "+TLT" then
t = { }
setmetatable(t,mt_lre)
@@ -412,7 +415,7 @@ end
local function get_baselevel(head,list,size) -- todo: skip if first is object (or pass head and test for localpar)
local id = getid(head)
if id == localpar_code then
- if getfield(head,"dir") == "TRT" then
+ if getdir(head) == "TRT" then
return 1, "TRT", true
else
return 0, "TLT", true
@@ -930,13 +933,13 @@ local function apply_to_list(list,size,head,pardir)
setcolor(current,direction,false,mirror)
end
elseif id == hlist_code or id == vlist_code then
- setfield(current,"dir",pardir) -- is this really needed?
+ setdir(current,pardir) -- is this really needed?
elseif id == glue_code then
if enddir and getsubtype(current) == parfillskip_code then
-- insert the last enddir before \parfillskip glue
local d = new_textdir(enddir)
local p = properties[d] if p then p.directions = true else properties[d] = { directions = true } end
- -- setfield(d,"attr",getfield(current,"attr"))
+ -- setattrlist(d,current)
head = insert_node_before(head,current,d)
enddir = false
done = true
@@ -946,7 +949,7 @@ local function apply_to_list(list,size,head,pardir)
-- localpar should always be the 1st node
local d = new_textdir(begindir)
local p = properties[d] if p then p.directions = true else properties[d] = { directions = true } end
- -- setfield(d,"attr",getfield(current,"attr"))
+ -- setattrlist(d,current)
head, current = insert_node_after(head,current,d)
begindir = nil
done = true
@@ -955,7 +958,7 @@ local function apply_to_list(list,size,head,pardir)
if begindir then
local d = new_textdir(begindir)
local p = properties[d] if p then p.directions = true else properties[d] = { directions = true } end
- -- setfield(d,"attr",getfield(current,"attr"))
+ -- setattrlist(d,current)
head = insert_node_before(head,current,d)
done = true
end
@@ -969,7 +972,7 @@ local function apply_to_list(list,size,head,pardir)
if enddir then
local d = new_textdir(enddir)
local p = properties[d] if p then p.directions = true else properties[d] = { directions = true } end
- -- setfield(d,"attr",getfield(current,"attr"))
+ -- setattrlist(d,current)
head, current = insert_node_after(head,current,d)
done = true
end
diff --git a/tex/context/base/mkiv/typo-fkr.lua b/tex/context/base/mkiv/typo-fkr.lua
index b235ff284..a1135d0f3 100644
--- a/tex/context/base/mkiv/typo-fkr.lua
+++ b/tex/context/base/mkiv/typo-fkr.lua
@@ -23,6 +23,8 @@ local getkernpair = fonts.handlers.otf.getkern
local insert_before = nuts.insert_before
local new_kern = nuts.pool.fontkern
+local enableaction = nodes.tasks.enableaction
+
local a_extrakern = attributes.private("extrafontkern")
-- 0=none 1=min 2=max 3=mixed
@@ -112,7 +114,7 @@ if context then
local function setextrafontkerns(str)
if not enabled then
- nodes.tasks.enableaction("processors","typesetters.fontkerns.handler")
+ enableaction("processors","typesetters.fontkerns.handler")
enabled = true
end
setattribute(a_extrakern,values[str] or unsetvalue)
diff --git a/tex/context/base/mkiv/typo-fln.lua b/tex/context/base/mkiv/typo-fln.lua
index fcd9b2c1f..cef77cea1 100644
--- a/tex/context/base/mkiv/typo-fln.lua
+++ b/tex/context/base/mkiv/typo-fln.lua
@@ -21,7 +21,10 @@ typesetters.firstlines = typesetters.firstlines or { }
local firstlines = typesetters.firstlines
local nodes = nodes
+
local tasks = nodes.tasks
+local enableaction = tasks.enableaction
+local disableaction = tasks.disableaction
local context = context
local implement = interfaces.implement
@@ -45,6 +48,7 @@ local getbox = nuts.getbox
local getdisc = nuts.getdisc
local setdisc = nuts.setdisc
local setlink = nuts.setlink
+local setfont = nuts.setfont
local nodecodes = nodes.nodecodes
local glyph_code = nodecodes.glyph
@@ -87,7 +91,7 @@ local settings = nil
function firstlines.set(specification)
settings = specification or { }
- tasks.enableaction("processors","typesetters.firstlines.handler")
+ enableaction("processors","typesetters.firstlines.handler")
if trace_firstlines then
report_firstlines("enabling firstlines")
end
@@ -131,7 +135,7 @@ actions[v_line] = function(head,setting)
if dynamic > 0 then
setattr(g,0,dynamic)
end
- setfield(g,"font",font)
+ setfont(g,font)
end
end
@@ -207,7 +211,7 @@ actions[v_line] = function(head,setting)
if dynamic > 0 then
setattr(start,0,dynamic)
end
- setfield(start,"font",font)
+ setfont(start,font)
if ca and ca > 0 then
setattr(start,a_colormodel,ma == 0 and 1 or ma)
setattr(start,a_color,ca)
@@ -311,7 +315,7 @@ actions[v_word] = function(head,setting)
if dynamic > 0 then
setattr(start,0,dynamic)
end
- setfield(start,"font",font)
+ setfont(start,font)
elseif id == disc_code then
-- continue
elseif id == kern_code then -- todo: fontkern
@@ -345,7 +349,7 @@ function firstlines.handler(head)
end
if attr then
-- here as we can process nested boxes first so we need to keep state
- tasks.disableaction("processors","typesetters.firstlines.handler")
+ disableaction("processors","typesetters.firstlines.handler")
-- texsetattribute(attribute,unsetvalue)
local alternative = settings.alternative or v_default
local action = actions[alternative] or actions[v_default]
diff --git a/tex/context/base/mkiv/typo-itc.lua b/tex/context/base/mkiv/typo-itc.lua
index 61a1bfe6c..312832d5b 100644
--- a/tex/context/base/mkiv/typo-itc.lua
+++ b/tex/context/base/mkiv/typo-itc.lua
@@ -23,7 +23,7 @@ local glue_code = nodecodes.glue
local disc_code = nodecodes.disc
local math_code = nodecodes.math
-local tasks = nodes.tasks
+local enableaction = nodes.tasks.enableaction
local nuts = nodes.nuts
local nodepool = nuts.pool
@@ -40,9 +40,14 @@ local getchar = nuts.getchar
local getdisc = nuts.getdisc
local getattr = nuts.getattr
local setattr = nuts.setattr
+local getattrlist = nuts.getattrlist
+local setattrlist = nuts.setattrlist
local setfield = nuts.setfield
local setdisc = nuts.setdisc
local isglyph = nuts.isglyph
+local setkern = nuts.setkern
+local getkern = nuts.getkern
+local getheight = nuts.getheight
local insert_node_after = nuts.insert_after
local delete_node = nuts.delete
@@ -124,7 +129,7 @@ local function okay(data,current,font,prevchar,previtalic,char,what)
return false
end
if threshold then
- local ht = getfield(current,"height")
+ local ht = getheight(current)
local ex = exheights[font]
local th = threshold * ex
if ht <= th then
@@ -149,9 +154,9 @@ end
local function correction_kern(kern,n)
local k = new_correction_kern(kern)
if n then
- local a = getfield(n,"attr")
+ local a = getattrlist(n)
if a then -- maybe not
- setfield(k,"attr",a) -- can be a marked content (border case)
+ setattrlist(k,a) -- can be a marked content (border case)
end
end
return k
@@ -160,9 +165,9 @@ end
local function correction_glue(glue,n)
local g = new_correction_glue(glue)
if n then
- local a = getfield(n,"attr")
+ local a = getattrlist(n)
if a then -- maybe not
- setfield(g,"attr",a) -- can be a marked content (border case)
+ setattrlist(g,a) -- can be a marked content (border case)
end
end
return g
@@ -195,10 +200,10 @@ local function domath(head,current, done)
else
a = a + 100
end
- local i = getfield(kern,"kern")
+ local i = getkern(kern)
local f = getfont(glyph)
local c = getchar(glyph)
- if getfield(next,"height") < 1.25*exheights[f] then
+ if getheight(next) < 1.25*exheights[f] then
if i == 0 then
if trace_italics then
report_italics("%s italic %p between math %C and punctuation %C","ignoring",i,c,char)
@@ -207,7 +212,7 @@ local function domath(head,current, done)
if trace_italics then
report_italics("%s italic between math %C and punctuation %C","removing",i,c,char)
end
- setfield(kern,"kern",0) -- or maybe a small value or half the ic
+ setkern(kern,0) -- or maybe a small value or half the ic
done = true
end
elseif i == 0 then
@@ -218,7 +223,7 @@ local function domath(head,current, done)
report_italics("%s italic %p between math %C and punctuation %C","ignoring",i,c,char)
end
else
- setfield(kern,"kern",i)
+ setkern(kern,i)
if trace_italics then
report_italics("%s italic %p between math %C and punctuation %C","setting",i,c,char)
end
@@ -593,7 +598,7 @@ function italics.handler(head)
end
enabletext = function()
- tasks.enableaction("processors","typesetters.italics.handler")
+ enableaction("processors","typesetters.italics.handler")
if trace_italics then
report_italics("enabling text/text italics")
end
@@ -602,7 +607,7 @@ enabletext = function()
end
enablemath = function()
- tasks.enableaction("processors","typesetters.italics.handler")
+ enableaction("processors","typesetters.italics.handler")
if trace_italics then
report_italics("enabling math/text italics")
end
diff --git a/tex/context/base/mkiv/typo-krn.lua b/tex/context/base/mkiv/typo-krn.lua
index 6a2aed9a2..24a91d6b6 100644
--- a/tex/context/base/mkiv/typo-krn.lua
+++ b/tex/context/base/mkiv/typo-krn.lua
@@ -14,7 +14,8 @@ local next, type, tonumber = next, type, tonumber
local nodes = nodes
local fonts = fonts
-local tasks = nodes.tasks
+local enableaction = nodes.tasks.enableaction
+
local nuts = nodes.nuts
local nodepool = nuts.pool
@@ -28,23 +29,27 @@ local flush_node = nuts.flush_node
local insert_node_before = nuts.insert_before
local insert_node_after = nuts.insert_after
local end_of_math = nuts.end_of_math
+local use_components = nuts.use_components
local getfield = nuts.getfield
local getnext = nuts.getnext
local getprev = nuts.getprev
-local getboth = nuts.getboth
local getid = nuts.getid
local getfont = nuts.getfont
local getsubtype = nuts.getsubtype
local getchar = nuts.getchar
local getdisc = nuts.getdisc
+local getglue = nuts.getglue
+local getkern = nuts.getkern
local isglyph = nuts.isglyph
local setfield = nuts.setfield
local getattr = nuts.getattr
-local setattr = nuts.setattr
+local takeattr = nuts.takeattr
local setlink = nuts.setlink
-local setsubtype = nuts.setsubtype
+local setdisc = nuts.setdisc
+local setglue = nuts.setglue
+local setkern = nuts.setkern
local texsetattribute = tex.setattribute
local unsetvalue = attributes.unsetvalue
@@ -105,10 +110,6 @@ local report = logs.reporter("kerns")
local trace_ligatures = false trackers.register("typesetters.kerns.ligatures", function(v) trace_ligatures = v end)
local trace_ligatures_d = false trackers.register("typesetters.kerns.ligatures.detail",function(v) trace_ligatures_d = v end)
--- use_advance is just an experiment: it makes copying glyphs (instead of new_glyph) dangerous
-
-local use_advance = false directives.register("typesetters.kerns.advance", function(v) use_advance = v end)
-
kerns.mapping = kerns.mapping or { }
kerns.factors = kerns.factors or { }
local a_kerns = attributes.private("kern")
@@ -232,8 +233,7 @@ local function inject_begin(boundary,prev,keeptogether,krn,ok) -- prev is a glyp
end
if inject then
-- not yet ok, as injected kerns can be overlays (from node-inj.lua)
- setsubtype(boundary,userkern_code)
- setfield(boundary,"kern",getfield(boundary,"kern") + quaddata[getfont(prev)]*krn)
+ setkern(boundary,getkern(boundary) + quaddata[getfont(prev)]*krn,userkern_code)
return boundary, true
end
end
@@ -269,8 +269,7 @@ local function inject_end(boundary,next,keeptogether,krn,ok)
end
if inject then
-- not yet ok, as injected kerns can be overlays (from node-inj.lua)
- setsubtype(tail,userkern_code)
- setfield(tail,"kern",getfield(tail,"kern") + quaddata[getfont(next)]*krn)
+ setkern(tail,getkern(tail) + quaddata[getfont(next)]*krn,userkern_code)
return boundary, true
end
end
@@ -284,7 +283,7 @@ local function inject_end(boundary,next,keeptogether,krn,ok)
local data = chardata[font][nextchar]
local kerns = data and data.kerns
local kern = (kerns and kerns[char] or 0) + quaddata[font]*krn
- insert_node_after(boundary,tail,new_kern(kern))
+ setlink(tail,new_kern(kern))
return boundary, true
end
end
@@ -320,8 +319,7 @@ local function process_list(head,keeptogether,krn,font,okay)
end
if inject then
-- not yet ok, as injected kerns can be overlays (from node-inj.lua)
- setsubtype(prev,userkern_code)
- setfield(prev,"kern",getfield(prev,"kern") + kern)
+ setkern(prev,getkern(prev) + kern,userkern_code)
okay = true
end
end
@@ -383,9 +381,8 @@ function kerns.handler(head)
-- fontkerns don't get the attribute but they always sit between glyphs so
-- are always valid bound .. disc nodes also somtimes don't get them
local id = getid(start)
- local attr = getattr(start,a_kerns)
+ local attr = takeattr(start,a_kerns)
if attr and attr > 0 then
- setattr(start,a_kerns,0) -- unsetvalue)
local krn = mapping[attr]
if krn == v_max then
krn = .25
@@ -395,31 +392,13 @@ function kerns.handler(head)
end
if not krn or krn == 0 then
bound = false
- elseif id == glyph_code then -- we could use the subtype ligature
- local c = getfield(start,"components")
- if not c then
- -- fine
- elseif keepligature and keepligature(start) then
+ elseif id == glyph_code then
+ if keepligature and keepligature(start) then
-- keep 'm
- c = nil
else
- while c do
- local s = start
- local t = find_node_tail(c)
- local p, n = getboth(s)
- if p then
- setlink(p,c)
- else
- head = c
- end
- if n then
- setlink(t,n)
- end
- start = c
- setfield(s,"components",nil)
- flush_node(s)
- c = getfield(start,"components")
- end
+ -- we could use the subtype ligature but that's also a call
+ -- todo: check tounicode and use that information to split
+ head, start = use_components(head,start)
end
local char = getchar(start)
local font = getfont(start)
@@ -438,8 +417,7 @@ function kerns.handler(head)
end
if inject then
-- not yet ok, as injected kerns can be overlays (from node-inj.lua)
- setsubtype(prev,userkern_code)
- setfield(prev,"kern",getfield(prev,"kern") + quaddata[font]*krn)
+ setkern(prev,getkern(prev) + quaddata[font]*krn,userkern_code)
done = true
end
end
@@ -451,11 +429,7 @@ function kerns.handler(head)
local data = chardata[font][prevchar]
local kerns = data and data.kerns
local kern = (kerns and kerns[char] or 0) + quaddata[font]*krn
- if not fillup and use_advance then
- setfield(prev,"xadvance",getfield(prev,"xadvance") + kern)
- else
- insert_node_before(head,start,kern_injector(fillup,kern))
- end
+ insert_node_before(head,start,kern_injector(fillup,kern))
done = true
end
else
@@ -485,12 +459,7 @@ function kerns.handler(head)
languages.expand(start,pglyph and prev)
end
local pre, post, replace = getdisc(start)
- -- we really need to reasign the fields as luatex keeps track of
- -- the tail in a temp preceding head .. kind of messy so we might
- -- want to come up with a better solution some day like a real
- -- pretail etc fields in a disc node
- --
- -- maybe i'll merge the now split functions
+ local indeed = false
if pre then
local okay = false
if not prev then
@@ -502,8 +471,7 @@ function kerns.handler(head)
end
pre, okay = process_list(pre,keeptogether,krn,false,okay)
if okay then
- setfield(start,"pre",pre)
- done = true
+ indeed = true
end
end
if post then
@@ -517,8 +485,7 @@ function kerns.handler(head)
end
post, okay = process_list(post,keeptogether,krn,false,okay)
if okay then
- setfield(start,"post",post)
- done = true
+ indeed = true
end
end
if replace then
@@ -539,11 +506,14 @@ function kerns.handler(head)
end
replace, okay = process_list(replace,keeptogether,krn,false,okay)
if okay then
- setfield(start,"replace",replace)
- done = true
+ indeed = true
end
elseif prevfont then
- setfield(start,"replace",new_kern(quaddata[prevfont]*krn))
+ replace = new_kern(quaddata[prevfont]*krn)
+ indeed = true
+ end
+ if indeed then
+ setdisc(start,pre,post,replace)
done = true
end
bound = false
@@ -554,21 +524,18 @@ function kerns.handler(head)
elseif id == glue_code then
local subtype = getsubtype(start)
if subtype == userskip_code or subtype == xspaceskip_code or subtype == spaceskip_code then
- local w = getfield(start,"width")
- if w > 0 then
- local width = w + gluefactor * w * krn
- local stretch = getfield(start,"stretch") * width / w
- local shrink = getfield(start,"shrink") * width / w
+ local width, stretch, shrink, stretch_order, shrink_order = getglue(start)
+ if width > 0 then
+ local w = width + gluefactor * width * krn
+ stretch = stretch * w / width
+ shrink = shrink * w / width
if fillup then
stretch = 2 * stretch
shrink = 2 * shrink
- setfield(start,"stretch_order",1)
- -- shrink_order ?
+ stretch_order = 1
+ -- shrink_order = 1 ?
end
- setfield(start,"width",width)
- setfield(start,"stretch",stretch)
- setfield(start,"shrink", shrink)
- --
+ setglue(start,w,stretch,shrink,stretch_order,shrink_order)
done = true
end
end
@@ -617,7 +584,7 @@ function kerns.set(factor)
end
if factor == v_max or factor ~= 0 then
if not enabled then
- tasks.enableaction("processors","typesetters.kerns.handler")
+ enableaction("processors","typesetters.kerns.handler")
enabled = true
end
local a = factors[factor]
diff --git a/tex/context/base/mkiv/typo-lin.lua b/tex/context/base/mkiv/typo-lin.lua
index 119b94cdc..d702bcb8c 100644
--- a/tex/context/base/mkiv/typo-lin.lua
+++ b/tex/context/base/mkiv/typo-lin.lua
@@ -89,6 +89,14 @@ local getprev = nuts.getprev
local getboth = nuts.getboth
local getfield = nuts.getfield
local setfield = nuts.setfield
+local setlink = nuts.setlink
+local setkern = nuts.setkern
+local getkern = nuts.getkern
+local getdir = nuts.getdir
+local getshift = nuts.getshift
+local setshift = nuts.setshift
+local getwidth = nuts.getwidth
+local setwidth = nuts.setwidth
local setprop = nuts.setprop
local getprop = nuts.rawprop -- getprop
@@ -135,8 +143,8 @@ local function finalize(prop,key) -- delayed calculations
local line = prop.line
local hsize = prop.hsize
local width = prop.width
- local shift = getfield(line,"shift") -- dangerous as it can be vertical as well
- local reverse = getfield(line,"dir") == "TRT" or false
+ local shift = getshift(line) -- dangerous as it can be vertical as well
+ local reverse = getdir(line) == "TRT" or false
local pack = new_hlist()
local head = getlist(line)
local delta = 0
@@ -168,7 +176,7 @@ local function normalize(line,islocal) -- assumes prestine lines, nothing pre/ap
local head = oldhead
local leftskip = nil
local rightskip = nil
- local width = getfield(line,"width")
+ local width = getwidth(line)
local hsize = islocal and width or tex.hsize
local lskip = 0
local rskip = 0
@@ -179,7 +187,7 @@ local function normalize(line,islocal) -- assumes prestine lines, nothing pre/ap
local subtype = getsubtype(head)
if subtype == leftskip_code then
leftskip = head
- lskip = getfield(head,"width") or 0
+ lskip = getwidth(head) or 0
end
current = getnext(head)
id = getid(current)
@@ -194,7 +202,7 @@ local function normalize(line,islocal) -- assumes prestine lines, nothing pre/ap
if id == glue_code then
if getsubtype(current) == rightskip_code then
rightskip = tail
- rskip = getfield(current,"width") or 0
+ rskip = getwidth(current) or 0
current = getprev(tail)
id = getid(current)
end
@@ -355,12 +363,14 @@ local function addanchortoline(n,anchor)
local anchor = tonut(anchor)
local where = line.where
if trace_anchors then
- local rule1 = new_rule(65536/2,4*65536,4*65536)
- local rule2 = new_rule(8*65536,65536/4,65536/4)
- local kern1 = new_kern(-65536/4)
- local kern2 = new_kern(-65536/4-4*65536)
- anchor = new_hlist(nuts.link { anchor, kern1, rule1, kern2, rule2 })
- setfield(anchor,"width",0)
+ anchor = new_hlist(setlink(
+ anchor,
+ new_kern(-65536/4),
+ new_rule(65536/2,4*65536,4*65536),
+ new_kern(-65536/4-4*65536),
+ new_rule(8*65536,65536/4,65536/4)
+ ))
+ setwidth(anchor,0)
end
if where.tail then
local head = where.head
@@ -393,15 +403,15 @@ function paragraphs.moveinline(n,blob,dx,dy)
if dx ~= 0 then
local prev, next = getboth(blob)
if prev and getid(prev) == kern_code then
- setfield(prev,"kern",getfield(prev,"kern") + dx)
+ setkern(prev,getkern(prev) + dx)
end
if next and getid(next) == kern_code then
- setfield(next,"kern",getfield(next,"kern") - dx)
+ setkern(next,getkern(next) - dx)
end
end
if dy ~= 0 then
if getid(blob) == hlist_code then
- setfield(blob,"shift",getfield(blob,"shift") + dy)
+ setshift(blob,getshift(blob) + dy)
end
end
else
diff --git a/tex/context/base/mkiv/typo-mar.lua b/tex/context/base/mkiv/typo-mar.lua
index 680fb20cc..a5d607cd7 100644
--- a/tex/context/base/mkiv/typo-mar.lua
+++ b/tex/context/base/mkiv/typo-mar.lua
@@ -64,7 +64,6 @@ local tonut = nuts.tonut
local hpack_nodes = nuts.hpack
local traverse_id = nuts.traverse_id
local flush_node_list = nuts.flush_list
-local linked_nodes = nuts.linked
local getfield = nuts.getfield
local setfield = nuts.setfield
@@ -78,6 +77,11 @@ local getlist = nuts.getlist
local getwhd = nuts.getwhd
local setlist = nuts.setlist
local setlink = nuts.setlink
+local getshift = nuts.getshift
+local setshift = nuts.setshift
+local getwidth = nuts.getwidth
+local setwidth = nuts.setwidth
+local getheight = nuts.getheight
local getbox = nuts.getbox
local takebox = nuts.takebox
@@ -95,8 +99,6 @@ local vlist_code = nodecodes.vlist
local whatsit_code = nodecodes.whatsit
local userdefined_code = whatsitcodes.userdefined
-local n_flush_node = nodes.flush
-
local nodepool = nuts.pool
local new_usernumber = nodepool.usernumber
@@ -486,10 +488,9 @@ local function markovershoot(current) -- todo: alleen als offset > line
v_anchors = v_anchors + 1
cache[v_anchors] = fastcopy(stacked)
local anchor = setanchor(v_anchors)
- -- local list = hpack_nodes(linked_nodes(anchor,getlist(current))) -- not ok, we need to retain width
- local list = hpack_nodes(linked_nodes(anchor,getlist(current)),getfield(current,"width"),"exactly")--
- -- why not:
- -- local list = linked_nodes(anchor,getlist(current))
+ -- local list = hpack_nodes(setlink(anchor,getlist(current))) -- not ok, we need to retain width
+ -- local list = setlink(anchor,getlist(current)) -- why not this ... better play safe
+ local list = hpack_nodes(setlink(anchor,getlist(current)),getwidth(current),"exactly")--
if trace_marginstack then
report_margindata("marking anchor %a",v_anchors)
end
@@ -503,7 +504,7 @@ local function inject(parent,head,candidate)
end
local width, height, depth
= getwhd(box)
- local shift = getfield(box,"shift")
+ local shift = getshift(box)
local stack = candidate.stack
local stackname = candidate.stackname
local location = candidate.location
@@ -544,7 +545,7 @@ local function inject(parent,head,candidate)
end
end
candidate.width = width
- candidate.hsize = getfield(parent,"width") -- we can also pass textwidth
+ candidate.hsize = getwidth(parent) -- we can also pass textwidth
candidate.psubtype = psubtype
candidate.stackname = stackname
if trace_margindata then
@@ -617,7 +618,7 @@ local function inject(parent,head,candidate)
-- following which we don't know yet ... so, consider stacking partially
-- experimental.
if method == v_top then
- local delta = height - getfield(parent,"height")
+ local delta = height - getheight(parent)
if trace_margindata then
report_margindata("top aligned by %p",delta)
end
@@ -671,8 +672,8 @@ local function inject(parent,head,candidate)
shift = shift + delta
offset = offset + delta
end
- setfield(box,"shift",shift)
- setfield(box,"width",0) -- not needed when wrapped
+ setshift(box,shift)
+ setwidth(box,0) -- not needed when wrapped
--
if isstacked then
setlink(box,addtoanchor(v_anchor,nofinjected))
@@ -785,7 +786,7 @@ local function flushed(scope,parent) -- current is hlist
if done then
local a = getattr(head,a_linenumber) -- hack .. we need a more decent critical attribute inheritance mechanism
if false then
- local l = hpack_nodes(head,getfield(parent,"width"),"exactly")
+ local l = hpack_nodes(head,getwidth(parent),"exactly")
setlist(parent,l)
if a then
setattr(l,a_linenumber,a)
@@ -947,14 +948,6 @@ end
-- Somehow the vbox builder (in combinations) gets pretty confused and decides to
-- go horizontal. So this needs more testing.
-prependaction("finalizers", "lists", "typesetters.margins.localhandler")
-prependaction("mvlbuilders", "normalizers", "typesetters.margins.globalhandler")
-prependaction("shipouts", "normalizers", "typesetters.margins.finalhandler")
-
-disableaction("finalizers", "typesetters.margins.localhandler")
-disableaction("mvlbuilders", "typesetters.margins.globalhandler")
-disableaction("shipouts", "typesetters.margins.finalhandler")
-
enablelocal = function()
enableaction("finalizers", "typesetters.margins.localhandler")
enableaction("shipouts", "typesetters.margins.finalhandler")
diff --git a/tex/context/base/mkiv/typo-pag.lua b/tex/context/base/mkiv/typo-pag.lua
index 063b5214a..d6f71c8cc 100644
--- a/tex/context/base/mkiv/typo-pag.lua
+++ b/tex/context/base/mkiv/typo-pag.lua
@@ -34,8 +34,13 @@ local getnext = nuts.getnext
local getprev = nuts.getprev
local getid = nuts.getid
local getattr = nuts.getattr
+local takeattr = nuts.takeattr
local setattr = nuts.setattr
local getwhd = nuts.getwhd
+local getkern = nuts.getkern
+local setpenalty = nuts.setpenalty
+local getwidth = nuts.getwidth
+local getdepth = nuts.getdepth
local insert_node_after = nuts.insert_after
local new_penalty = nuts.pool.penalty
@@ -43,6 +48,8 @@ local new_penalty = nuts.pool.penalty
local trace_keeptogether = false
local report_keeptogether = logs.reporter("parbuilders","keeptogether")
+local enableaction = nodes.tasks.enableaction
+
local cache = { }
local last = 0
local enabled = false
@@ -57,7 +64,7 @@ function parbuilders.registertogether(line,specification) -- might change
return
end
if not enabled then
- nodes.tasks.enableaction("finalizers","builders.paragraphs.keeptogether")
+ enableaction("finalizers","builders.paragraphs.keeptogether")
end
local a = getattr(line,a_keeptogether)
local c = a and cache[a]
@@ -110,7 +117,7 @@ local function keeptogether(start,a)
if a then
local current = getnext(start)
local previous = start
- local total = getfield(previous,"depth")
+ local total = getdepth(previous)
local slack = specification.slack
local threshold = specification.depth - slack
if trace_keeptogether then
@@ -126,7 +133,7 @@ local function keeptogether(start,a)
end
if total <= threshold then
if getid(previous) == penalty_code then
- setfield(previous,"penalty",10000)
+ setpenalty(previous,10000)
else
insert_node_after(head,previous,new_penalty(10000))
end
@@ -135,13 +142,13 @@ local function keeptogether(start,a)
end
elseif id == glue_code then
-- hm, breakpoint, maybe turn this into kern
- total = total + getfield(current,"width")
+ total = total + getwidth(current)
if trace_keeptogether then
report_keeptogether("%s, index %s, total %p, threshold %p","glue",a,total,threshold)
end
if total <= threshold then
if getid(previous) == penalty_code then
- setfield(previous,"penalty",10000)
+ setpenalty(previous,10000)
else
insert_node_after(head,previous,new_penalty(10000))
end
@@ -149,13 +156,13 @@ local function keeptogether(start,a)
break
end
elseif id == kern_code then
- total = total + getfield(current,"kern")
+ total = total + getkern(current)
if trace_keeptogether then
report_keeptogether("%s, index %s, total %s, threshold %s","kern",a,total,threshold)
end
if total <= threshold then
if getid(previous) == penalty_code then
- setfield(previous,"penalty",10000)
+ setpenalty(previous,10000)
else
insert_node_after(head,previous,new_penalty(10000))
end
@@ -165,9 +172,9 @@ local function keeptogether(start,a)
elseif id == penalty_code then
if total <= threshold then
if getid(previous) == penalty_code then
- setfield(previous,"penalty",10000)
+ setpenalty(previous,10000)
end
- setfield(current,"penalty",10000)
+ setpenalty(current,10000)
else
break
end
@@ -186,10 +193,9 @@ function parbuilders.keeptogether(head)
local current = tonut(head)
while current do
if getid(current) == hlist_code then
- local a = getattr(current,a_keeptogether)
+ local a = takeattr(current,a_keeptogether)
if a and a > 0 then
keeptogether(current,a)
- setattr(current,a_keeptogether,unsetvalue)
cache[a] = nil
done = true
end
diff --git a/tex/context/base/mkiv/typo-rep.lua b/tex/context/base/mkiv/typo-rep.lua
index 489877792..5266aa103 100644
--- a/tex/context/base/mkiv/typo-rep.lua
+++ b/tex/context/base/mkiv/typo-rep.lua
@@ -18,7 +18,7 @@ local trace_stripping = false trackers.register("nodes.stripping", function(v)
local report_stripping = logs.reporter("fonts","stripping")
local nodes = nodes
-local tasks = nodes.tasks
+local enableaction = nodes.tasks.enableaction
local nuts = nodes.nuts
local tonut = nuts.tonut
@@ -119,7 +119,7 @@ function stripping.set(n) -- number or 'reset'
if n then
if not enabled then
if initialize then initialize() end
- tasks.enableaction("processors","nodes.handlers.stripping")
+ enableaction("processors","nodes.handlers.stripping")
enabled = true
end
else
@@ -129,11 +129,6 @@ function stripping.set(n) -- number or 'reset'
texsetattribute(a_stripping,n)
end
--- why not in task-ini?
-
-tasks.appendaction("processors","fonts","nodes.handlers.stripping",nil,"nodes.handlers.characters")
-tasks.disableaction("processors","nodes.handlers.stripping")
-
-- interface
interfaces.implement {
diff --git a/tex/context/base/mkiv/typo-rub.lua b/tex/context/base/mkiv/typo-rub.lua
index f101668b6..9621a6218 100644
--- a/tex/context/base/mkiv/typo-rub.lua
+++ b/tex/context/base/mkiv/typo-rub.lua
@@ -48,9 +48,14 @@ local setprev = nuts.setprev
local setlink = nuts.setlink
local getlist = nuts.getlist
local setlist = nuts.setlist
+local setshift = nuts.setshift
+local getwidth = nuts.getwidth
+local setwidth = nuts.setwidth
+
local hpack = nuts.hpack
local insert_after = nuts.insert_after
local takebox = nuts.takebox
+local traverse_id = nuts.traverse_id
local nodecodes = nodes.nodecodes
local glyph_code = nodecodes.glyph
@@ -70,12 +75,13 @@ local kerncodes = nodes.kerncodes
local font_code = kerncodes.font
local nodepool = nuts.pool
-local new_hlist = nodepool.hlist
local new_kern = nodepool.kern
local setprop = nuts.setprop
local getprop = nuts.getprop
+local enableaction = nodes.tasks.enableaction
+
local nofrubies = 0
local rubylist = { }
@@ -93,8 +99,8 @@ do
local splitter = lpeg.tsplitat("|")
local function enable()
- nodes.tasks.enableaction("processors","typesetters.rubies.check")
- nodes.tasks.enableaction("shipouts", "typesetters.rubies.attach")
+ enableaction("processors","typesetters.rubies.check")
+ enableaction("shipouts", "typesetters.rubies.attach")
enable = false
end
@@ -173,7 +179,7 @@ do
local r = takebox(n)
rubylist[nofrubies] = setmetatableindex({
text = r,
- width = getfield(r,"width"),
+ width = getwidth(r),
basewidth = 0,
start = false,
stop = false,
@@ -210,7 +216,7 @@ function rubies.check(head)
setlink(prev,h)
end
setlink(h,next)
- local bwidth = getfield(h,"width")
+ local bwidth = getwidth(h)
local rwidth = r.width
r.basewidth = bwidth
r.start = start
@@ -218,7 +224,7 @@ function rubies.check(head)
setprop(h,"ruby",found)
if rwidth > bwidth then
-- ruby is wider
- setfield(h,"width",rwidth)
+ setwidth(h,rwidth)
end
end
end
@@ -259,121 +265,129 @@ function rubies.check(head)
return tonode(head), true
end
-local function attach(head,parent)
- local current = head
- while current do
- local id = getid(current)
- if id == hlist_code then
- local a = getprop(current,"ruby")
- if a then
- local ruby = rubylist[a]
- local align = ruby.align or v_middle
- local stretch = ruby.stretch or v_no
- local hoffset = ruby.hoffset or 0
- local voffset = ruby.voffset or 0
- local start = ruby.start
- local stop = ruby.stop
- local text = ruby.text
- local rwidth = ruby.width
- local bwidth = ruby.basewidth
- local delta = rwidth - bwidth
- setfield(text,"width",0)
- if voffset ~= 0 then
- setfield(text,"shift",voffset)
+local attach
+
+local function whatever(current)
+ local a = getprop(current,"ruby")
+ if a then
+ local ruby = rubylist[a]
+ local align = ruby.align or v_middle
+ local stretch = ruby.stretch or v_no
+ local hoffset = ruby.hoffset or 0
+ local voffset = ruby.voffset or 0
+ local start = ruby.start
+ local stop = ruby.stop
+ local text = ruby.text
+ local rwidth = ruby.width
+ local bwidth = ruby.basewidth
+ local delta = rwidth - bwidth
+ setwidth(text,0)
+ if voffset ~= 0 then
+ setshift(text,voffset)
+ end
+ -- center them
+ if delta > 0 then
+ -- ruby is wider
+ if stretch == v_yes then
+ setlink(text,start)
+ while start and start ~= stop do
+ local s = nodepool.stretch()
+ local n = getnext(start)
+ setlink(start,s,n)
+ start = n
end
- -- center them
- if delta > 0 then
- -- ruby is wider
- if stretch == v_yes then
- setlink(text,start)
- while start and start ~= stop do
- local s = nodepool.stretch()
- local n = getnext(start)
- setlink(start,s)
- setlink(s,n)
- start = n
- end
- text = hpack(text,rwidth,"exactly")
+ text = hpack(text,rwidth,"exactly")
+ else
+ local left = new_kern(delta/2)
+ local right = new_kern(delta/2)
+-- setlink(left,start)
+-- setlink(stop,right)
+-- setlink(text,left)
+ setlink(text,left,start)
+ setlink(stop,right)
+ end
+ setlist(current,text)
+ elseif delta < 0 then
+ -- ruby is narrower
+ if align == v_auto then
+ local l = true
+ local c = getprev(current)
+ while c do
+ local id = getid(c)
+ if id == glue_code or id == penalty_code or id == kern_code or (id == whatsit_code and getsubtype(current,localpar_code)) then
+ -- go on
+ elseif id == hlist_code and getwidth(c) == 0 then
+ -- go on
+ elseif id == whatsit_code or id == localpar_code then
+ -- go on
else
- local left = new_kern(delta/2)
- local right = new_kern(delta/2)
- setlink(left,start)
- setlink(stop,right)
- setlink(text,left)
- end
- setlist(current,text)
- elseif delta < 0 then
- -- ruby is narrower
- if align == v_auto then
- local l = true
- local c = getprev(current)
- while c do
- local id = getid(c)
- if id == glue_code or id == penalty_code or id == kern_code or (id == whatsit_code and getsubtype(current,localpar_code)) then
- -- go on
- elseif id == hlist_code and getfield(c,"width") == 0 then
- -- go on
- elseif id == whatsit_code or id == localpar_code then
- -- go on
- else
- l = false
- break
- end
- c = getprev(c)
- end
- local r = true
- local c = getnext(current)
- while c do
- local id = getid(c)
- if id == glue_code or id == penalty_code or id == kern_code then
- -- go on
- elseif id == hlist_code and getfield(c,"width") == 0 then
- -- go on
- else
- r = false
- break
- end
- c = getnext(c)
- end
- if l and not r then
- align = v_flushleft
- elseif r and not l then
- align = v_flushright
- else
- align = v_middle
- end
+ l = false
+ break
end
- if align == v_flushleft then
- setlink(text,start)
- setlist(current,text)
- elseif align == v_flushright then
- local left = new_kern(-delta)
- local right = new_kern(delta)
- setlink(left,text)
- setlink(text,right)
- setlink(right,start)
- setlist(current,left)
+ c = getprev(c)
+ end
+ local r = true
+ local c = getnext(current)
+ while c do
+ local id = getid(c)
+ if id == glue_code or id == penalty_code or id == kern_code then
+ -- go on
+ elseif id == hlist_code and getwidth(c) == 0 then
+ -- go on
else
- local left = new_kern(-delta/2)
- local right = new_kern(delta/2)
- setlink(left,text)
- setlink(text,right)
- setlink(right,start)
- setlist(current,left)
+ r = false
+ break
end
+ c = getnext(c)
+ end
+ if l and not r then
+ align = v_flushleft
+ elseif r and not l then
+ align = v_flushright
else
- setlink(text,start)
- setlist(current,text)
+ align = v_middle
end
- setprop(current,"ruby",false)
- rubylist[a] = nil
+ end
+ if align == v_flushleft then
+ setlink(text,start)
+ setlist(current,text)
+ elseif align == v_flushright then
+ local left = new_kern(-delta)
+ local right = new_kern(delta)
+-- setlink(left,text)
+-- setlink(text,right)
+-- setlink(right,start)
+ setlink(left,text,right,start)
+ setlist(current,left)
else
- attach(getlist(current),current)
+ local left = new_kern(-delta/2)
+ local right = new_kern(delta/2)
+-- setlink(left,text)
+-- setlink(text,right)
+-- setlink(right,start)
+ setlink(left,text,right,start)
+ setlist(current,left)
end
- elseif id == vlist_code then
- attach(getlist(current),current)
+ else
+ setlink(text,start)
+ setlist(current,text)
+ end
+ setprop(current,"ruby",false)
+ rubylist[a] = nil
+ else
+ local list = getlist(current)
+ if list then
+ attach(list)
end
- current = getnext(current)
+ end
+end
+
+attach = function(head)
+ for current in traverse_id(hlist_code,head) do
+ whatever(current)
+ end
+ for current in traverse_id(vlist_code,head) do
+ whatever(current)
end
return head, true
end
diff --git a/tex/context/base/mkiv/typo-rub.mkiv b/tex/context/base/mkiv/typo-rub.mkiv
index 0ebc1d4a4..7b996089b 100644
--- a/tex/context/base/mkiv/typo-rub.mkiv
+++ b/tex/context/base/mkiv/typo-rub.mkiv
@@ -21,7 +21,7 @@
\registerctxluafile{typo-rub}{1.001}
-\definesystemattribute[ruby]
+\definesystemattribute[ruby][public]
\installcorenamespace {ruby}
\installcorenamespace {rubyanalyze}
diff --git a/tex/context/base/mkiv/typo-spa.lua b/tex/context/base/mkiv/typo-spa.lua
index d1aa2e277..bda139719 100644
--- a/tex/context/base/mkiv/typo-spa.lua
+++ b/tex/context/base/mkiv/typo-spa.lua
@@ -14,8 +14,6 @@ local report_spacing = logs.reporter("typesetting","spacing")
local nodes, fonts, node = nodes, fonts, node
-local tasks = nodes.tasks
-
local fonthashes = fonts.hashes
local quaddata = fonthashes.quads
@@ -31,8 +29,7 @@ local tonode = nuts.tonode
local getnext = nuts.getnext
local getprev = nuts.getprev
local getfont = nuts.getfont
-local getattr = nuts.getattr
-local setattr = nuts.setattr
+local takeattr = nuts.takeattr
local isglyph = nuts.isglyph
local insert_node_before = nuts.insert_before
@@ -50,6 +47,8 @@ local math_code = nodecodes.math
local somespace = nodes.somespace
local somepenalty = nodes.somepenalty
+local enableaction = nodes.tasks.enableaction
+
typesetters = typesetters or { }
local typesetters = typesetters
@@ -82,12 +81,11 @@ function spacings.handler(head)
while start do
local char, id = isglyph(start)
if char then
- local attr = getattr(start,a_spacings)
+ local attr = takeattr(start,a_spacings)
if attr and attr > 0 then
local data = mapping[attr]
if data then
local map = data.characters[char]
- setattr(start,a_spacings,unsetvalue) -- needed?
if map then
local left = map.left
local right = map.right
@@ -210,7 +208,7 @@ function spacings.set(name)
local data = numbers[name]
if data then
if not enabled then
- tasks.enableaction("processors","typesetters.spacings.handler")
+ enableaction("processors","typesetters.spacings.handler")
enabled = true
end
n = data.number or unsetvalue
diff --git a/tex/context/base/mkiv/typo-sus.lua b/tex/context/base/mkiv/typo-sus.lua
index d3526bb5d..e81b36b65 100644
--- a/tex/context/base/mkiv/typo-sus.lua
+++ b/tex/context/base/mkiv/typo-sus.lua
@@ -48,9 +48,11 @@ local getfield = nuts.getfield
local getattr = nuts.getattr
local getfont = nuts.getfont
local getlist = nuts.getlist
+local getkern = nuts.getkern
+local getpenalty = nuts.getpenalty
+local getwidth = nuts.getwidth
local isglyph = nuts.isglyph
-local setfield = nuts.setfield
local setattr = nuts.setattr
local setlist = nuts.setlist
@@ -72,22 +74,21 @@ local a_suspect = attributes.private('suspect')
local texsetattribute = tex.setattribute
local enabled = false
+local enableaction = nodes.tasks.enableaction
+
local threshold = 65536 / 4
local function special(n)
if n then
local id = getid(n)
if id == kern_code then
- local kern = getfield(n,"kern")
- return kern < threshold
+ return getkern(n) < threshold
elseif id == penalty_code then
return true
elseif id == glue_code then
- local width = getfield(n,"width")
- return width < threshold
+ return getwidth(n) < threshold
elseif id == hlist_code then
- local width = getfield(n,"width")
- return width < threshold
+ return getwidth(n) < threshold
end
else
return false
@@ -118,21 +119,21 @@ local function mark(head,current,id,color)
if id == glue_code then
-- the glue can have stretch and/or shrink so the rule can overlap with the
-- following glyph .. no big deal as that one then sits on top of the rule
- local width = getfield(current,"width")
+ local width = getwidth(current)
local rule = new_rule(width)
local kern = new_kern(-width)
head = insert_before(head,current,rule)
head = insert_before(head,current,kern)
setcolor(rule,color)
-- elseif id == kern_code then
- -- local width = getfield(current,"kern")
+ -- local width = getkern(current)
-- local rule = new_rule(width)
-- local kern = new_kern(-width)
-- head = insert_before(head,current,rule)
-- head = insert_before(head,current,kern)
-- setcolor(rule,color)
else
- local width, height, depth = getWhd(current)
+ local width, height, depth = getwhd(current)
local extra = fonts.hashes.xheights[getfont(current)] / 2
local rule = new_rule(width,height+extra,depth+extra)
local hlist = new_hlist(rule)
@@ -232,7 +233,7 @@ function typesetters.marksuspects(head)
local prev = getprev(current)
local prid = prev and getid(prev)
local done = false
- if prid == penalty_code and getfield(prev,"penalty") == 10000 then
+ if prid == penalty_code and getpenalty(prev) == 10000 then
done = 8 -- orange
else
done = 5 -- darkmagenta
@@ -292,19 +293,13 @@ function typesetters.showsuspects(head)
end
end
-nodes.tasks.appendaction ("processors","after", "typesetters.marksuspects")
-nodes.tasks.prependaction("shipouts", "normalizers","typesetters.showsuspects")
-
-nodes.tasks.disableaction("processors","typesetters.marksuspects")
-nodes.tasks.disableaction("shipouts", "typesetters.showsuspects")
-
-- or maybe a directive
trackers.register("typesetters.suspects",function(v)
texsetattribute(a_suspecting,v and 1 or unsetvalue)
if v and not enabled then
- nodes.tasks.enableaction("processors","typesetters.marksuspects")
- nodes.tasks.enableaction("shipouts", "typesetters.showsuspects")
+ enableaction("processors","typesetters.marksuspects")
+ enableaction("shipouts", "typesetters.showsuspects")
enabled = true
end
end)
diff --git a/tex/context/base/mkiv/typo-tal.lua b/tex/context/base/mkiv/typo-tal.lua
index b3a1601d9..67380f24b 100644
--- a/tex/context/base/mkiv/typo-tal.lua
+++ b/tex/context/base/mkiv/typo-tal.lua
@@ -41,11 +41,9 @@ local getprev = nuts.getprev
local getid = nuts.getid
local getfont = nuts.getfont
local getchar = nuts.getchar
-local getfield = nuts.getfield
local getattr = nuts.getattr
local isglyph = nuts.isglyph
-local setfield = nuts.setfield
local setattr = nuts.setattr
local setchar = nuts.setchar
@@ -64,6 +62,8 @@ local tracers = nodes.tracers
local setcolor = tracers.colors.set
local tracedrule = tracers.pool.nuts.rule
+local enableaction = nodes.tasks.enableaction
+
local characteralign = { }
typesetters.characteralign = characteralign
@@ -102,7 +102,7 @@ local validsigns = {
local function setcharacteralign(column,separator)
if not enabled then
- nodes.tasks.enableaction("processors","typesetters.characteralign.handler")
+ enableaction("processors","typesetters.characteralign.handler")
enabled = true
end
if not datasets then
diff --git a/tex/context/base/mkiv/typo-wrp.lua b/tex/context/base/mkiv/typo-wrp.lua
index 394e15090..07e34cd6c 100644
--- a/tex/context/base/mkiv/typo-wrp.lua
+++ b/tex/context/base/mkiv/typo-wrp.lua
@@ -23,9 +23,11 @@ local find_node_tail = nuts.tail
local getprev = nuts.getprev
local getid = nuts.getid
local getsubtype = nuts.getsubtype
-local getfield = nuts.getfield
+local getpenalty = nuts.getpenalty
local remove = nuts.remove
+local enableaction = nodes.tasks.enableaction
+
local wrappers = { }
typesetters.wrappers = wrappers
@@ -39,9 +41,9 @@ local report = logs.reporter("paragraphs","wrappers")
local function remove_dangling_crlf(head,tail)
if tail and getid(tail) == glue_code and getsubtype(tail) == parfill_skip_code then
tail = getprev(tail)
- if tail and getid(tail) == penalty_code and getsubtype(tail) == user_penalty_code and getfield(tail,"penalty") == 10000 then
+ if tail and getid(tail) == penalty_code and getsubtype(tail) == user_penalty_code and getpenalty(tail) == 10000 then
tail = getprev(tail)
- if tail and getid(tail) == penalty_code and getsubtype(tail) == user_penalty_code and getfield(tail,"penalty") == -10000 then
+ if tail and getid(tail) == penalty_code and getsubtype(tail) == user_penalty_code and getpenalty(tail) == -10000 then
if tail == head then
-- can't happen
else
@@ -71,6 +73,6 @@ interfaces.implement {
name = "enablecrlf",
onlyonce = true,
actions = function()
- nodes.tasks.enableaction("processors","typesetters.wrappers.handler")
+ enableaction("processors","typesetters.wrappers.handler")
end
}
diff --git a/tex/context/base/mkiv/util-fil.lua b/tex/context/base/mkiv/util-fil.lua
index 0f9731a26..cf97d9541 100644
--- a/tex/context/base/mkiv/util-fil.lua
+++ b/tex/context/base/mkiv/util-fil.lua
@@ -93,7 +93,7 @@ end
function files.readinteger1(f) -- one byte
local n = byte(f:read(1))
- if n >= 0x80 then
+ if n >= 0x80 then
-- return n - 0xFF - 1
return n - 0x100
else
@@ -124,6 +124,14 @@ function files.readinteger2(f)
return n
end
end
+ function files.readinteger2(f)
+ local a, b = byte(f:read(2),1,2)
+ if a >= 0x80 then
+ return 0x100 * a + b - 0x10000
+ else
+ return 0x100 * a + b
+ end
+ end
function files.readinteger2le(f)
local b, a = byte(f:read(2),1,2)
local n = 0x100 * a + b
@@ -184,6 +192,14 @@ function files.readinteger4(f)
return n
end
end
+ function files.readinteger4(f)
+ local a, b, c, d = byte(f:read(4),1,4)
+ if a >= 0x80 then
+ return 0x1000000 * a + 0x10000 * b + 0x100 * c + d - 0x100000000
+ else
+ return 0x1000000 * a + 0x10000 * b + 0x100 * c + d
+ end
+ end
function files.readinteger4le(f)
local d, c, b, a = byte(f:read(4),1,4)
local n = 0x1000000 * a + 0x10000 * b + 0x100 * c + d
diff --git a/tex/context/base/mkiv/util-sbx.lua b/tex/context/base/mkiv/util-sbx.lua
index 260e8b3b5..03593cb9b 100644
--- a/tex/context/base/mkiv/util-sbx.lua
+++ b/tex/context/base/mkiv/util-sbx.lua
@@ -23,19 +23,23 @@ local platform = os.type
local P, S, C = lpeg.P, lpeg.S, lpeg.C
local gsub = string.gsub
local lower = string.lower
+local find = string.find
+local concat = string.concat
local unquoted = string.unquoted
local optionalquoted = string.optionalquoted
+local basename = file.basename
local sandbox = sandbox
local validroots = { }
local validrunners = { }
-local validbinaries = { }
+local validbinaries = true -- all permitted
+local validlibraries = true -- all permitted
local validators = { }
-local p_validroot = nil
local finalized = nil
-local norunners = false
local trace = false
-local p_split = lpeg.tsplitat(" ") -- more spaces?
+
+local p_validroot = nil
+local p_split = lpeg.firstofsplit(" ")
local report = logs.reporter("sandbox")
@@ -43,9 +47,12 @@ trackers.register("sandbox",function(v) trace = v end) -- often too late anyway
sandbox.setreporter(report)
-sandbox.finalizer(function()
- finalized = true
-end)
+sandbox.finalizer {
+ category = "files",
+ action = function()
+ finalized = true
+ end
+}
local function registerroot(root,what) -- what == read|write
if finalized then
@@ -60,52 +67,57 @@ local function registerroot(root,what) -- what == read|write
end
end
-sandbox.finalizer(function() -- initializers can set the path
- if p_validroot then
- report("roots are already initialized")
- else
- sandbox.registerroot(".","write") -- always ok
- -- also register texmf as read
- for name in sortedhash(validroots) do
- if p_validroot then
- p_validroot = P(name) + p_validroot
- else
- p_validroot = P(name)
+sandbox.finalizer {
+ category = "files",
+ action = function() -- initializers can set the path
+ if p_validroot then
+ report("roots are already initialized")
+ else
+ sandbox.registerroot(".","write") -- always ok
+ -- also register texmf as read
+ for name in sortedhash(validroots) do
+ if p_validroot then
+ p_validroot = P(name) + p_validroot
+ else
+ p_validroot = P(name)
+ end
end
+ p_validroot = p_validroot / validroots
end
- p_validroot = p_validroot / validroots
end
-end)
+}
-local function registerrunner(specification)
+local function registerbinary(name)
if finalized then
- report("runners are already finalized")
- else
- local name = specification.name
- if not name then
- report("no runner name specified")
+ report("binaries are already finalized")
+ elseif type(name) == "string" and name ~= "" then
+ if not validbinaries then
return
end
- local program = specification.program
- if type(program) == "string" then
- -- common for all platforms
- elseif type(program) == "table" then
- program = program[platform]
- end
- if type(program) ~= "string" or program == "" then
- report("invalid runner %a specified for platform %a",name,platform)
- return
+ if validbinaries == true then
+ validbinaries = { [name] = true }
+ else
+ validbinaries[name] = true
end
- specification.program = program
- validrunners[name] = specification
+ elseif name == true then
+ validbinaries = { }
end
end
-local function registerbinary(name)
+local function registerlibrary(name)
if finalized then
- report("binaries are already finalized")
+ report("libraries are already finalized")
elseif type(name) == "string" and name ~= "" then
- validbinaries[name] = true
+ if not validlibraries then
+ return
+ end
+ if validlibraries == true then
+ validlibraries = { [name] = true }
+ else
+ validlibraries[name] = true
+ end
+ elseif name == true then
+ validlibraries = { }
end
end
@@ -173,7 +185,7 @@ local function validfilename(name,what)
end
end
-local function readable(name)
+local function readable(name,finalized)
if platform == "windows" then
name = lower(name) -- we assume ascii names
end
@@ -183,7 +195,7 @@ local function readable(name)
end
end
-local function writeable(name)
+local function writeable(name,finalized)
if platform == "windows" then
name = lower(name) -- we assume ascii names
end
@@ -193,8 +205,8 @@ local function writeable(name)
end
end
-validators.readable = readable
validators.writeable = writeable
+validators.readable = readable
validators.filename = readable
table.setmetatableindex(validators,function(t,k)
@@ -204,23 +216,39 @@ table.setmetatableindex(validators,function(t,k)
return readable
end)
-function validators.string(s)
- return s -- can be used to prevent filename checking
+function validators.string(s,finalized)
+ -- can be used to prevent filename checking (todo: only when registered)
+ if finalized and suspicious(s) then
+ return ""
+ else
+ return s
+ end
end
--- end of validators
+function validators.cache(s)
+ if finalized then
+ return basename(s)
+ else
+ return s
+ end
+end
+
+function validators.url(s)
+ if finalized and find("^file:") then
+ return ""
+ else
+ return s
+ end
+end
-sandbox.registerroot = registerroot
-sandbox.registerrunner = registerrunner
-sandbox.registerbinary = registerbinary
-sandbox.validfilename = validfilename
+-- end of validators
local function filehandlerone(action,one,...)
local checkedone = validfilename(one)
if checkedone then
return action(one,...)
else
--- report("file %a is unreachable",one)
+ -- report("file %a is unreachable",one)
end
end
@@ -231,10 +259,10 @@ local function filehandlertwo(action,one,two,...)
if checkedtwo then
return action(one,two,...)
else
--- report("file %a is unreachable",two)
+ -- report("file %a is unreachable",two)
end
else
--- report("file %a is unreachable",one)
+ -- report("file %a is unreachable",one)
end
end
@@ -254,101 +282,276 @@ end
-- runners can be strings or tables
--
-- os.execute : string
--- os.exec : table with program in [0|1]
--- os.spawn : table with program in [0|1]
+-- os.exec : string or table with program in [0|1]
+-- os.spawn : string or table with program in [0|1]
--
-- our execute: registered program with specification
-local function runhandler(action,name,specification)
- local kind = type(name)
- if kind ~= "string" then
+local osexecute = sandbox.original(os.execute)
+local iopopen = sandbox.original(io.popen)
+local reported = { }
+
+local function validcommand(name,program,template,checkers,defaults,variables,reporter,strict)
+ if validbinaries ~= false and (validbinaries == true or validbinaries[program]) then
+ if variables then
+ for variable, value in next, variables do
+ local checker = validators[checkers[variable]]
+ if checker then
+ value = checker(unquoted(value),strict)
+ if value then
+ variables[variable] = optionalquoted(value)
+ else
+ report("variable %a with value %a fails the check",variable,value)
+ return
+ end
+ else
+ report("variable %a has no checker",variable)
+ return
+ end
+ end
+ for variable, default in next, defaults do
+ local value = variables[variable]
+ if not value or value == "" then
+ local checker = validators[checkers[variable]]
+ if checker then
+ default = checker(unquoted(default),strict)
+ if default then
+ variables[variable] = optionalquoted(default)
+ else
+ report("variable %a with default %a fails the check",variable,default)
+ return
+ end
+ end
+ end
+ end
+ end
+ local command = program .. " " .. replace(template,variables)
+ if reporter then
+ reporter("executing runner %a: %s",name,command)
+ elseif trace then
+ report("executing runner %a: %s",name,command)
+ end
+ return command
+ elseif not reported[name] then
+ report("executing program %a of runner %a is not permitted",program,name)
+ reported[name] = true
+ end
+end
+
+local runners = {
+ --
+ -- name,program,template,checkers,variables,reporter
+ --
+ resultof = function(...)
+ local command = validcommand(...)
+ if command then
+ local handle = iopopen(command,"r") -- already has flush
+ if handle then
+ local result = handle:read("*all") or ""
+ handle:close()
+ return result
+ end
+ end
+ end,
+ execute = function(...)
+ local command = validcommand(...)
+ if command then
+ return osexecute(command)
+ end
+ end,
+ pipeto = function(...)
+ local command = validcommand(...)
+ if command then
+ return iopopen(command,"w") -- already has flush
+ end
+ end,
+}
+
+function sandbox.registerrunner(specification)
+ if type(specification) == "string" then
+ local wrapped = validrunners[specification]
+ inspect(table.sortedkeys(validrunners))
+ if wrapped then
+ return wrapped
+ else
+ report("unknown predefined runner %a",specification)
+ return
+ end
+ end
+ if type(specification) ~= "table" then
+ report("specification should be a table (or string)")
return
end
- if norunners then
- report("no runners permitted, ignoring command: %s",name)
+ local name = specification.name
+ if type(name) ~= "string" then
+ report("invalid name, string expected")
return
end
- local spec = validrunners[name]
- if not spec then
- report("unknown runner: %s",name)
+ if validrunners[name] then
+ report("invalid name, runner %a already defined")
return
end
- -- specs are already checked
- local program = spec.program
- local variables = { }
- local checkers = spec.checkers or { }
- if specification then
- -- we only handle runners that are defined before the sandbox is
- -- closed so in principle we cannot have user runs with no files
- -- while for context runners we assume a robust specification
- for k, v in next, specification do
- local checker = validators[checkers[k]]
- local value = checker(unquoted(v)) -- todo: write checkers
- if value then
- variables[k] = optionalquoted(value)
- else
- report("suspicious argument found, run blocked: %s",v)
- return
- end
- end
+ local program = specification.program
+ if type(program) == "string" then
+ -- common for all platforms
+ elseif type(program) == "table" then
+ program = program[platform] or program.default or program.unix
+ end
+ if type(program) ~= "string" or program == "" then
+ report("invalid runner %a specified for platform %a",name,platform)
+ return
+ end
+ local template = specification.template
+ if not template then
+ report("missing template for runner %a",name)
+ return
end
- local command = replace(program,variables)
- if trace then
- report("executing runner: %s",command)
+ local method = specification.method or "execute"
+ local checkers = specification.checkers or { }
+ local defaults = specification.defaults or { }
+ local runner = runners[method]
+ if runner then
+ local finalized = finalized -- so, the current situation is frozen
+ local wrapped = function(variables)
+ return runner(name,program,template,checkers,defaults,variables,specification.reporter,finalized)
+ end
+ validrunners[name] = wrapped
+ return wrapped
+ else
+ validrunners[name] = nil
+ report("invalid method for runner %a",name)
end
- return action(command)
end
--- only registered (from list) -- no checking on writable so let's assume harmless
--- runs
+local function suspicious(str)
+ return (find(str,"[/\\]") or find(command,"%.%.")) and true or false
+end
-local function binaryhandler(action,name)
- local kind = type(name)
- local list = name
- if kind == "string" then
- list = lpegmatch(p_split,name)
+local function binaryrunner(action,command,...)
+ if validbinaries == false then
+ -- nothing permitted
+ report("no binaries permitted, ignoring command: %s",command)
+ return
end
- local program = name[0] or name[1]
- if type(program) ~= "string" or program == "" then
- return --silently ignore
+ if type(command) ~= "string" then
+ -- we only handle strings, maybe some day tables
+ report("command should be a string")
+ return
end
- if norunners then
- report("no binaries permitted, ignoring command: %s",program)
+ local program = lpegmatch(p_split,command)
+ if not program or program == "" then
+ report("unable to filter binary from command: %s",command)
return
end
- if not validbinaries[program] then
- report("binary is not permitted: %s",program)
+ if validbinaries == true then
+ -- everything permitted
+ elseif not validbinaries[program] then
+ report("binary not permitted, ignoring command: %s",command)
+ return
+ elseif suspicious(command) then
+ report("/ \\ or .. found, ignoring command (use sandbox.registerrunner): %s",command)
return
end
- for i=0,#list do
- local n = list[i]
- if n then
- local v = readable(unquoted(n))
- if v then
- list[i] = optionalquoted(v)
- else
- report("suspicious argument found, run blocked: %s",n)
- return
- end
- end
+ return action(command,...)
+end
+
+-- local function binaryrunner(action,command,...)
+-- local original = command
+-- if validbinaries == false then
+-- -- nothing permitted
+-- report("no binaries permitted, ignoring command: %s",command)
+-- return
+-- end
+-- local program
+-- if type(command) == "table" then
+-- program = command[0]
+-- if program then
+-- command = concat(command," ",0)
+-- else
+-- program = command[1]
+-- if program then
+-- command = concat(command," ")
+-- end
+-- end
+-- elseif type(command) = "string" then
+-- program = lpegmatch(p_split,command)
+-- else
+-- report("command should be a string or table")
+-- return
+-- end
+-- if not program or program == "" then
+-- report("unable to filter binary from command: %s",command)
+-- return
+-- end
+-- if validbinaries == true then
+-- -- everything permitted
+-- elseif not validbinaries[program] then
+-- report("binary not permitted, ignoring command: %s",command)
+-- return
+-- elseif find(command,"[/\\]") or find(command,"%.%.") then
+-- report("/ \\ or .. found, ignoring command (use sandbox.registerrunner): %s",command)
+-- return
+-- end
+-- return action(original,...)
+-- end
+
+local function dummyrunner(action,command,...)
+ if type(command) == "table" then
+ command = concat(command," ",command[0] and 0 or 1)
end
- return action(name)
+ report("ignoring command: %s",command)
end
sandbox.filehandlerone = filehandlerone
sandbox.filehandlertwo = filehandlertwo
sandbox.iohandler = iohandler
-sandbox.runhandler = runhandler
-sandbox.binaryhandler = binaryhandler
function sandbox.disablerunners()
- norunners = true
+ validbinaries = false
end
-local execute = sandbox.original(os.execute)
+function sandbox.disablelibraries()
+ validlibraries = false
+end
+
+if ffi then
+
+ function sandbox.disablelibraries()
+ validlibraries = false
+ for k, v in next, ffi do
+ if k ~= "gc" then
+ ffi[k] = nil
+ end
+ end
+ end
+
+ local load = ffi.load
+
+ if load then
+
+ local reported = { }
+
+ function ffi.load(name,...)
+ if validlibraries == false then
+ -- all blocked
+ elseif validlibraries == true then
+ -- all permitted
+ return load(name,...)
+ elseif validlibraries[name] then
+ -- 'name' permitted
+ return load(name,...)
+ else
+ -- 'name' not permitted
+ end
+ if not reported[name] then
+ report("using library %a is not permitted",name)
+ reported[name] = true
+ end
+ return nil
+ end
+
+ end
-function sandbox.run(name,specification)
- return runhandler(execute,name,specification)
end
-------------------
@@ -360,16 +563,18 @@ local register = sandbox.register
if io then
overload(io.open, filehandlerone,"io.open")
- overload(io.popen, filehandlerone,"io.popen")
+ overload(io.popen, binaryrunner, "io.popen")
overload(io.input, iohandler, "io.input")
overload(io.output, iohandler, "io.output")
overload(io.lines, filehandlerone,"io.lines")
end
if os then
- overload(os.execute, binaryhandler, "os.execute")
- overload(os.spawn, binaryhandler, "os.spawn")
- overload(os.exec, binaryhandler, "os.exec")
+ overload(os.execute, binaryrunner, "os.execute")
+ overload(os.spawn, dummyrunner, "os.spawn")
+ overload(os.exec, dummyrunner, "os.exec")
+ overload(os.resultof, binaryrunner, "os.resultof")
+ overload(os.pipeto, binaryrunner, "os.pipeto")
overload(os.rename, filehandlertwo,"os.rename")
overload(os.remove, filehandlerone,"os.remove")
end
@@ -406,6 +611,11 @@ if epdf then
epdf.open = register(epdf.open, filehandlerone,"epdf.open")
end
+sandbox.registerroot = registerroot
+sandbox.registerbinary = registerbinary
+sandbox.registerlibrary = registerlibrary
+sandbox.validfilename = validfilename
+
-- not used in a normal mkiv run : os.spawn = os.execute
-- not used in a normal mkiv run : os.exec = os.exec
diff --git a/tex/context/base/mkiv/util-seq.lua b/tex/context/base/mkiv/util-seq.lua
index 32fe59096..5836f5eca 100644
--- a/tex/context/base/mkiv/util-seq.lua
+++ b/tex/context/base/mkiv/util-seq.lua
@@ -293,7 +293,7 @@ sequencers.compile = compile
-- todo: use sequencer (can have arguments and returnvalues etc now)
-local template_yes = [[
+local template_yes_state = [[
%s
return function(head%s)
local ok, done = false, false
@@ -301,6 +301,13 @@ return function(head%s)
return head, done
end]]
+local template_yes_nostate = [[
+%s
+return function(head%s)
+%s
+ return head, true
+end]]
+
local template_nop = [[
return function()
return false, false
@@ -308,6 +315,7 @@ end]]
function sequencers.nodeprocessor(t,nofarguments) -- todo: handle 'kind' in plug into tostring
local list, order, kind, gskip, askip = t.list, t.order, t.kind, t.gskip, t.askip
+ local nostate = t.nostate
local vars, calls, args, n = { }, { }, nil, 0
if nofarguments == 0 then
args = ""
@@ -335,18 +343,24 @@ function sequencers.nodeprocessor(t,nofarguments) -- todo: handle 'kind' in plug
n = n + 1
vars[n] = formatters["local %s = %s"](localized,action)
-- only difference with tostring is kind and rets (why no return)
- if kind[action] == "nohead" then
- calls[n] = formatters[" ok = %s(head%s) done = done or ok"](localized,args)
+ if nostate then
+ if kind[action] == "nohead" then
+ calls[n] = formatters[" %s(head%s)"](localized,args)
+ else
+ calls[n] = formatters[" head = %s(head%s)"](localized,args)
+ end
else
- calls[n] = formatters[" head, ok = %s(head%s) done = done or ok"](localized,args)
+ if kind[action] == "nohead" then
+ calls[n] = formatters[" ok = %s(head%s) if ok then done = true end"](localized,args)
+ else
+ calls[n] = formatters[" head, ok = %s(head%s) if ok then done = true end"](localized,args)
+ end
end
--- local s = " print('" .. tostring(group) .. " " .. tostring(action) .. " : ' .. tostring(head)) "
--- calls[n] = s .. calls[n] .. s
end
end
end
end
- local processor = #calls > 0 and formatters[template_yes](concat(vars,"\n"),args,concat(calls,"\n")) or template_nop
+ local processor = #calls > 0 and formatters[nostate and template_yes_nostate or template_yes_state](concat(vars,"\n"),args,concat(calls,"\n")) or template_nop
-- print(processor)
return processor
end
diff --git a/tex/context/base/mkiv/util-sql-imp-client.lua b/tex/context/base/mkiv/util-sql-imp-client.lua
index 6a019bd3a..a2763feac 100644
--- a/tex/context/base/mkiv/util-sql-imp-client.lua
+++ b/tex/context/base/mkiv/util-sql-imp-client.lua
@@ -178,6 +178,8 @@ local function datafetched(specification)
if trace_sql then
local t = osclock()
report_state("command: %s",command)
+ -- for now we don't use sandbox.registerrunners as this module is
+ -- also used outside context
local okay = os.execute(command)
report_state("fetchtime: %.3f sec, return code: %i",osclock()-t,okay) -- not okay under linux
return okay == 0
diff --git a/tex/context/base/mkiv/util-sql-imp-sqlite.lua b/tex/context/base/mkiv/util-sql-imp-sqlite.lua
index bb789f648..1a960c1c3 100644
--- a/tex/context/base/mkiv/util-sql-imp-sqlite.lua
+++ b/tex/context/base/mkiv/util-sql-imp-sqlite.lua
@@ -26,7 +26,6 @@ local methods = sql.methods
local validspecification = helpers.validspecification
local preparetemplate = helpers.preparetemplate
local splitdata = helpers.splitdata
-local replacetemplate = utilities.templates.replace
local serialize = sql.serialize
local deserialize = sql.deserialize
local getserver = sql.getserver
diff --git a/tex/context/fonts/mkiv/cambria-math.lfg b/tex/context/fonts/mkiv/cambria-math.lfg
index 6415069e6..ae875e64d 100644
--- a/tex/context/fonts/mkiv/cambria-math.lfg
+++ b/tex/context/fonts/mkiv/cambria-math.lfg
@@ -44,6 +44,11 @@ return {
mathematics = {
parameters = {
DisplayOperatorMinHeight = FixDisplayOperatorMinHeight,
- }
- }
+ },
+ -- kernpairs = { -- \setupmathematics[kernpairs=yes]
+ -- [0x1D44E] = {
+ -- [0x1D44F] = 1000, -- 𝑎𝑏 demo
+ -- }
+ -- },
+ },
}
diff --git a/tex/context/fonts/mkiv/type-imp-ebgaramond.mkiv b/tex/context/fonts/mkiv/type-imp-ebgaramond.mkiv
index 838654d49..cd474242f 100644
--- a/tex/context/fonts/mkiv/type-imp-ebgaramond.mkiv
+++ b/tex/context/fonts/mkiv/type-imp-ebgaramond.mkiv
@@ -11,6 +11,8 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
+% Why so many features ... dead slow too
+
\definefontfeature
[eb-garamond-normal]
[default]
@@ -32,7 +34,7 @@
\setups[font:fallback:serif]
\definefontsynonym [Serif] [file:ebgaramond-regular] [features=eb-garamond-normal]
\definefontsynonym [SerifItalic] [file:ebgaramond-italic] [features=eb-garamond-normal]
- \definefontsynonym [SerifBold] [file:ebgaramond-bold] [features=eb-garamond-normal]
+ \definefontsynonym [SerifBold] [file:ebgaramond-regular] [features=eb-garamond-normal] % there is no bold
\definefontsynonym [SerifCaps] [Serif] [features=eb-garamond-smallcaps]
\stoptypescript
diff --git a/tex/context/interface/mkii/keys-cs.xml b/tex/context/interface/mkii/keys-cs.xml
index 65def6288..9ce2a779a 100644
--- a/tex/context/interface/mkii/keys-cs.xml
+++ b/tex/context/interface/mkii/keys-cs.xml
@@ -215,6 +215,7 @@
<cd:variable name='formulas' value='rovnice'/>
<cd:variable name='forward' value='vpred'/>
<cd:variable name='four' value='ctyri'/>
+ <cd:variable name='fractions' value='fractions'/>
<cd:variable name='frame' value='ramecek'/>
<cd:variable name='framedtext' value='oramovanytext'/>
<cd:variable name='friday' value='patek'/>
diff --git a/tex/context/interface/mkii/keys-de.xml b/tex/context/interface/mkii/keys-de.xml
index a607b6358..404f8da89 100644
--- a/tex/context/interface/mkii/keys-de.xml
+++ b/tex/context/interface/mkii/keys-de.xml
@@ -215,6 +215,7 @@
<cd:variable name='formulas' value='formeln'/>
<cd:variable name='forward' value='vorwaerts'/>
<cd:variable name='four' value='vier'/>
+ <cd:variable name='fractions' value='fractions'/>
<cd:variable name='frame' value='rahmen'/>
<cd:variable name='framedtext' value='umrahmtertext'/>
<cd:variable name='friday' value='freitag'/>
diff --git a/tex/context/interface/mkii/keys-en.xml b/tex/context/interface/mkii/keys-en.xml
index c84454f54..a1c935db8 100644
--- a/tex/context/interface/mkii/keys-en.xml
+++ b/tex/context/interface/mkii/keys-en.xml
@@ -215,6 +215,7 @@
<cd:variable name='formulas' value='formulas'/>
<cd:variable name='forward' value='forward'/>
<cd:variable name='four' value='four'/>
+ <cd:variable name='fractions' value='fractions'/>
<cd:variable name='frame' value='frame'/>
<cd:variable name='framedtext' value='framedtext'/>
<cd:variable name='friday' value='friday'/>
diff --git a/tex/context/interface/mkii/keys-fr.xml b/tex/context/interface/mkii/keys-fr.xml
index 725272f3c..db6e35ac6 100644
--- a/tex/context/interface/mkii/keys-fr.xml
+++ b/tex/context/interface/mkii/keys-fr.xml
@@ -215,6 +215,7 @@
<cd:variable name='formulas' value='formules'/>
<cd:variable name='forward' value='avance'/>
<cd:variable name='four' value='quatre'/>
+ <cd:variable name='fractions' value='fractions'/>
<cd:variable name='frame' value='cadre'/>
<cd:variable name='framedtext' value='texteencadre'/>
<cd:variable name='friday' value='vendredi'/>
diff --git a/tex/context/interface/mkii/keys-it.xml b/tex/context/interface/mkii/keys-it.xml
index d9642bf3a..86d6868b4 100644
--- a/tex/context/interface/mkii/keys-it.xml
+++ b/tex/context/interface/mkii/keys-it.xml
@@ -215,6 +215,7 @@
<cd:variable name='formulas' value='formule'/>
<cd:variable name='forward' value='avanti'/>
<cd:variable name='four' value='quattro'/>
+ <cd:variable name='fractions' value='fractions'/>
<cd:variable name='frame' value='cornice'/>
<cd:variable name='framedtext' value='testoincorniciato'/>
<cd:variable name='friday' value='venerdi'/>
diff --git a/tex/context/interface/mkii/keys-nl.xml b/tex/context/interface/mkii/keys-nl.xml
index add0efe38..1c6077d1e 100644
--- a/tex/context/interface/mkii/keys-nl.xml
+++ b/tex/context/interface/mkii/keys-nl.xml
@@ -215,6 +215,7 @@
<cd:variable name='formulas' value='formules'/>
<cd:variable name='forward' value='vooruit'/>
<cd:variable name='four' value='vier'/>
+ <cd:variable name='fractions' value='fractions'/>
<cd:variable name='frame' value='kader'/>
<cd:variable name='framedtext' value='kadertekst'/>
<cd:variable name='friday' value='vrijdag'/>
diff --git a/tex/context/interface/mkii/keys-pe.xml b/tex/context/interface/mkii/keys-pe.xml
index 6cb1bf833..91f778c5e 100644
--- a/tex/context/interface/mkii/keys-pe.xml
+++ b/tex/context/interface/mkii/keys-pe.xml
@@ -215,6 +215,7 @@
<cd:variable name='formulas' value='فرمولها'/>
<cd:variable name='forward' value='به‌جلو'/>
<cd:variable name='four' value='چهار'/>
+ <cd:variable name='fractions' value='fractions'/>
<cd:variable name='frame' value='قالب'/>
<cd:variable name='framedtext' value='متن‌قالبی'/>
<cd:variable name='friday' value='جمعه'/>
diff --git a/tex/context/interface/mkii/keys-ro.xml b/tex/context/interface/mkii/keys-ro.xml
index f1d644a29..a4566c4b4 100644
--- a/tex/context/interface/mkii/keys-ro.xml
+++ b/tex/context/interface/mkii/keys-ro.xml
@@ -215,6 +215,7 @@
<cd:variable name='formulas' value='formule'/>
<cd:variable name='forward' value='avans'/>
<cd:variable name='four' value='patru'/>
+ <cd:variable name='fractions' value='fractions'/>
<cd:variable name='frame' value='incadrat'/>
<cd:variable name='framedtext' value='textinconjurat'/>
<cd:variable name='friday' value='vineri'/>
diff --git a/tex/context/interface/mkiv/i-boxes.xml b/tex/context/interface/mkiv/i-boxes.xml
index fda2600e5..648106b89 100644
--- a/tex/context/interface/mkiv/i-boxes.xml
+++ b/tex/context/interface/mkiv/i-boxes.xml
@@ -444,7 +444,7 @@
<cd:content/>
</cd:arguments>
</cd:command>
-
+
<cd:command name="limitatelines" file="supp-box.mkiv">
<cd:arguments>
<cd:resolve name="argument-number"/>
@@ -1036,4 +1036,7 @@
</cd:arguments>
</cd:command>
+ <cd:command name="lastlinewidth" file="supp-box.mkiv">
+ </cd:command>
+
</cd:interface>
diff --git a/tex/context/interface/mkiv/i-context.pdf b/tex/context/interface/mkiv/i-context.pdf
index bf623a1eb..a3be00bdf 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-fonts.xml b/tex/context/interface/mkiv/i-fonts.xml
index 37542e1c9..46e8a0930 100644
--- a/tex/context/interface/mkiv/i-fonts.xml
+++ b/tex/context/interface/mkiv/i-fonts.xml
@@ -1063,6 +1063,8 @@
<cd:command name="settabular" file="font-pre.mkiv"/>
+ <cd:command name="setfractions" file="font-pre.mkiv"/>
+
<cd:command name="setsuperiors" file="font-pre.mkiv"/>
<cd:command name="tinyfont" file="font-pre.mkiv"/>
diff --git a/tex/context/interface/mkiv/i-readme.pdf b/tex/context/interface/mkiv/i-readme.pdf
index 850c10386..bcb7a4fb6 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/mkiv/m-matrix.mkiv b/tex/context/modules/mkiv/m-matrix.mkiv
index ccb376e39..b72453bdd 100644
--- a/tex/context/modules/mkiv/m-matrix.mkiv
+++ b/tex/context/modules/mkiv/m-matrix.mkiv
@@ -29,6 +29,8 @@ local copy = table.copy
local insert = table.insert
local remove = table.remove
+local context = context
+
local matrix = { }
moduledata.matrix = matrix
@@ -67,27 +69,58 @@ end
-- todo: define a matrix at the tex end so that we have more control
-local fences_p = {
- left = "\\left(\\,",
- right = "\\,\\right)",
+local fences = {
+ parentheses = { left = "\\left(\\,", right = "\\,\\right)" },
+ brackets = { left = "\\left[\\,", right = "\\,\\right]" },
+ bars = { left = "\\left|\\,", right = "\\,\\right|" },
}
-local fences_b = {
- left = "\\left[\\,",
- right = "\\,\\right]",
-}
+-- one can add more fences
+
+fences.bar = fences.bars
+fences.parenthesis = fences.parentheses
+fences.bracket = fences.brackets
+
+-- one can set the template
+
+matrix.template = "%0.3F"
function matrix.typeset(m,options)
- local options = settings_to_hash(options or "")
- context.startmatrix(options.determinant and fences_b or fences_p)
- for i=1, #m do
- local mi = m[i]
- for j=1,#mi do
- context.NC(mi[j])
- end
- context.NR()
+ if type(m) == "table" then
+ local options = settings_to_hash(options or "")
+ local whatever = options.determinant == "yes" and fences.bars or fences.parentheses
+ if options.fences then
+ whatever = fences[options.fences] or whatever
+ elseif options.determinant then
+ whatever = fences.brackets
+ -- whatever = fences.bars
+ end
+ local template = options.template or matrix.template
+ if template == "yes" then
+ template = matrix.template
+ elseif template == "no" then
+ template = false
+ elseif tonumber(template) then
+ template = "%0." .. template .. "F"
end
- context.stopmatrix()
+ context.startmatrix(whatever)
+ for i=1, #m do
+ local mi = m[i]
+ for j=1,#mi do
+ context.NC()
+ local n = mi[j]
+ if template and tonumber(n) then
+ context(template,n)
+ else
+ context(mi[j])
+ end
+ end
+ context.NR()
+ end
+ context.stopmatrix()
+ elseif m then
+ context(m)
+ end
end
-- interchange two rows (i-th, j-th)
@@ -151,7 +184,7 @@ function matrix.inner(u,v)
end
local nv = #v
if nv ~= nu then
- return 0
+ return "error: size mismatch"
end
local result = 0
for i=1,nu do
@@ -163,8 +196,8 @@ end
-- product of two matrices
function matrix.product(m1,m2)
- local product = { }
if #m1[1] == #m2 then
+ local product = { }
for i=1,#m1 do
local m1i = m1[i]
local mrow = { }
@@ -177,8 +210,10 @@ function matrix.product(m1,m2)
end
product[i] = mrow
end
+ return product
+ else
+ return "error: size mismatch"
end
- return product
end
local function uppertri(m,sign)
@@ -225,7 +260,7 @@ function matrix.determinant(m)
end
return s*d
else
- return 0
+ return "error: not a square matrix"
end
end
@@ -295,7 +330,7 @@ matrix.rowEchelon = rowechelon
-- solve the linear equation m X = c
-local function solve(m,c)
+local function solve(m,c)
local n = #m
if n ~= #c then
return copy(m)
@@ -393,14 +428,14 @@ moduledata.matrix.typeset(moduledata.matrix.multiply(document.DemoMatrixA, 2, 3)
\stopsubject
-\startsubject[title={Row 2 + $3 \times r_4$}]
+\startsubject[title={Row 2 + $4 \times r_3$}]
\startluacode
moduledata.matrix.typeset(document.DemoMatrixA)
context.blank()
moduledata.matrix.sumrow(document.DemoMatrixA, 2, 3, 4)
context.blank()
-moduledata.matrix.typeset(document.DemoMatrixA)
+moduledata.matrix.typeset(document.DemoMatrixA,{ fences = "bars" } )
\stopluacode
\stopsubject
@@ -445,7 +480,7 @@ local m = {
{ 0, 0, 2 },
{ 2, 2, -6 },
}
-context(moduledata.matrix.determinant(m))
+context(moduledata.matrix.determinant(m, "determinant=yes" ))
\stopluacode
\stopsubject
@@ -461,7 +496,8 @@ local m = {
}
moduledata.matrix.typeset(m)
-moduledata.matrix.typeset(moduledata.matrix.rowechelon(m,1))
+context.blank()
+moduledata.matrix.typeset(moduledata.matrix.rowechelon(m,1), { determinant = "yes" })
\stopluacode
\stopsubject
@@ -479,6 +515,14 @@ local m = {
local c = { 5, 2, 6, 8 }
moduledata.matrix.typeset(moduledata.matrix.solve(m,c))
+context.blank()
+moduledata.matrix.typeset(moduledata.matrix.solve(m,c), { template = 6 })
+context.blank()
+moduledata.matrix.typeset(moduledata.matrix.solve(m,c), { template = "no" })
+context.blank()
+moduledata.matrix.typeset(moduledata.matrix.solve(m,c), { template = "%0.3f" })
+context.blank()
+moduledata.matrix.typeset(moduledata.matrix.solve(m,c), { template = "%0.4F" })
\stopluacode
\stopsubject
diff --git a/tex/context/modules/mkiv/m-steps.lua b/tex/context/modules/mkiv/m-steps.lua
index 7fbb58370..ce84866a4 100644
--- a/tex/context/modules/mkiv/m-steps.lua
+++ b/tex/context/modules/mkiv/m-steps.lua
@@ -177,7 +177,6 @@ local function step_make_chart(settings)
start()
flush("step_begin_chart ;")
--
- print(chartsettings.alternative)
local alternative = chartsettings.alternative
if not alternative or alternative == "" then
alternative = chart.alternative
diff --git a/tex/context/modules/mkiv/m-steps.mkvi b/tex/context/modules/mkiv/m-steps.mkvi
index ce018a0d1..873015fd6 100644
--- a/tex/context/modules/mkiv/m-steps.mkvi
+++ b/tex/context/modules/mkiv/m-steps.mkvi
@@ -85,7 +85,8 @@
\setupSTEPlines
[\c!alternative=1,
\c!rulethickness=.15\bodyfontsize,
- \c!height=3\bodyfontsize,
+ \c!height=\STEPlineparameter\c!width,
+ \c!width=3\bodyfontsize,
\c!distance=.5\bodyfontsize,
\c!offset=.25\bodyfontsize,
\c!color=STEPlinecolor]
diff --git a/tex/context/modules/mkiv/s-inf-03.mkiv b/tex/context/modules/mkiv/s-inf-03.mkiv
index a253bed77..31333b8e5 100644
--- a/tex/context/modules/mkiv/s-inf-03.mkiv
+++ b/tex/context/modules/mkiv/s-inf-03.mkiv
@@ -16,7 +16,7 @@
\definefont
[TitlePageFont]
- [MonoBold at 15pt]
+ [MonoBold at 14pt]
\setupbodyfont
[tt,8pt]
@@ -25,7 +25,7 @@
\definefont
[TitlePageFont]
- [MonoBold at 18pt]
+ [MonoBold at 17pt]
\setupbodyfont
[tt]
@@ -159,7 +159,7 @@ local skipglobal = table.tohash {
"_G", "_M", "_ENV", "",
"context", "modules", "global", "arg", "utf", 1,
"_ptbs_", "_pcol_", "_plib_", "_clib_", "_tlib_",
- "kpse", "commands",
+ "kpse", "commands", "ffi",
}
local skipkeys = table.tohash {
diff --git a/tex/context/modules/mkiv/s-languages-hyphenation.lua b/tex/context/modules/mkiv/s-languages-hyphenation.lua
index 971ca3d8f..6d3cf3d3e 100644
--- a/tex/context/modules/mkiv/s-languages-hyphenation.lua
+++ b/tex/context/modules/mkiv/s-languages-hyphenation.lua
@@ -39,6 +39,8 @@ local getdisc = nuts.getdisc
local getattr = nuts.getattr
local getfont = nuts.getfont
local getfield = nuts.getfield
+local getlang = nuts.getlang
+local setlang = nuts.setlang
local setlink = nuts.setlink
local setdisc = nuts.setdisc
local setfield = nuts.setfield
@@ -129,7 +131,7 @@ local function getlanguage(head,l,left,right)
local t = { }
for n in traverse_by_id(glyph_code,tonut(head)) do
t[n] = {
- getfield(n,"lang"),
+ getlang(n),
getfield(n,"left"),
getfield(n,"right"),
}
@@ -148,7 +150,7 @@ function moduledata.languages.hyphenation.showhyphens(head)
-- somehow assigning -1 fails
for n in traverse_by_id(glyph_code,tonut(head)) do
cached[n] = {
- getfield(n,"lang"),
+ getlang(n),
getfield(n,"left"),
getfield(n,"right")
}
@@ -161,7 +163,7 @@ function moduledata.languages.hyphenation.showhyphens(head)
local lmin = s.lefthyphenmin
local rmin = s.righthyphenmin
for n in next, cached do
- setfield(n,"lang",l)
+ setlang(n,l)
setfield(n,"left",lmin)
setfield(n,"right",rmin)
end
@@ -173,7 +175,7 @@ function moduledata.languages.hyphenation.showhyphens(head)
mark(head,marked[i],1/16,l/2,l/4,"hyphenation:"..(colorbytag and tags[i] or i))
end
for n, d in next, cached do
- setfield(n,"lang",d[1])
+ setlang(n,d[1])
setfield(n,"left",d[2])
setfield(n,"right",d[3])
end
diff --git a/tex/context/sample/common/douglas.tex b/tex/context/sample/common/douglas.tex
index 838c6d24d..0aa9486e6 100644
--- a/tex/context/sample/common/douglas.tex
+++ b/tex/context/sample/common/douglas.tex
@@ -4,7 +4,7 @@ of his forthcoming books|=|from the typesetting and layout
down to the very shapes of the letters! Seldom has an
author had anything remotely like this power to control the
final appearance of his or her work. Knuth's \TEX\
-typesetting system has become well|-|known and as available in
+typesetting system has become well|-|known and is available in
many countries around the world. By contrast, his
\METAFONT\ system for designing families of typefaces has
not become as well known or as available.
diff --git a/tex/context/sample/common/knuth.tex b/tex/context/sample/common/knuth.tex
index 30b6310cc..2f6a2f8e7 100644
--- a/tex/context/sample/common/knuth.tex
+++ b/tex/context/sample/common/knuth.tex
@@ -13,4 +13,4 @@ But a system cannot be successful if it is too strongly
influenced by a single person. Once the initial design is
complete and fairly robust, the real test begins as people
with many different viewpoints undertake their own
-experiments.
+experiments.
diff --git a/tex/generic/context/luatex/luatex-basics-nod.lua b/tex/generic/context/luatex/luatex-basics-nod.lua
index 42a7a2e29..5571a82ba 100644
--- a/tex/generic/context/luatex/luatex-basics-nod.lua
+++ b/tex/generic/context/luatex/luatex-basics-nod.lua
@@ -171,6 +171,8 @@ nodes.mlist_to_hlist = node.mlist_to_hlist
-- we can go nuts (e.g. experimental); this split permits us us keep code
-- used elsewhere stable but at the same time play around in context
+-- much of this will go away
+
local direct = node.direct
local nuts = { }
nodes.nuts = nuts
@@ -201,16 +203,39 @@ nuts.setattr = setfield
nuts.getfont = direct.getfont
nuts.setfont = direct.setfont
nuts.getsubtype = direct.getsubtype
-nuts.setsubtype = direct.setsubtype or function(n,s) setfield(n,"subtype",s) end
+nuts.setsubtype = direct.setsubtype
nuts.getchar = direct.getchar
nuts.setchar = direct.setchar
nuts.getdisc = direct.getdisc
nuts.setdisc = direct.setdisc
nuts.setlink = direct.setlink
nuts.getlist = direct.getlist
-nuts.setlist = direct.setlist or function(n,l) setfield(n,"list",l) end
-nuts.getleader = direct.getleader
-nuts.setleader = direct.setleader or function(n,l) setfield(n,"leader",l) end
+nuts.setlist = direct.setlist
+
+nuts.getoffsets = direct.getoffsets or
+ function(n)
+ return getfield(n,"xoffset"), getfield(n,"yoffset")
+ end
+nuts.setoffsets = direct.setoffsets or
+ function(n,x,y)
+ if x then setfield(n,"xoffset",x) end
+ if y then setfield(n,"xoffset",y) end
+ end
+
+nuts.getleader = direct.getleader or function(n) return getfield(n,"leader") end
+nuts.setleader = direct.setleader or function(n,l) setfield(n,"leader",l) end
+nuts.getcomponents = direct.getcomponents or function(n) return getfield(n,"components") end
+nuts.setcomponents = direct.setcomponents or function(n,c) setfield(n,"components",c) end
+nuts.getkern = direct.getkern or function(n) return getfield(n,"kern") end
+nuts.setkern = direct.setkern or function(n,k) setfield(n,"kern",k) end
+nuts.getdir = direct.getkern or function(n) return getfield(n,"dir") end
+nuts.setdir = direct.setkern or function(n,d) setfield(n,"dir",d) end
+nuts.getwidth = direct.getwidth or function(n) return getfield(n,"width") end
+nuts.setwidth = direct.setwidth or function(n,w) return setfield(n,"width",w) end
+nuts.getheight = direct.getheight or function(n) return getfield(n,"height") end
+nuts.setheight = direct.setheight or function(n,h) return setfield(n,"height",h) end
+nuts.getdepth = direct.getdepth or function(n) return getfield(n,"depth") end
+nuts.setdepth = direct.setdepth or function(n,d) return setfield(n,"depth",d) end
if not direct.is_glyph then
local getchar = direct.getchar
@@ -312,3 +337,128 @@ end
nodes.setprop = nodes.setproperty
nodes.getprop = nodes.getproperty
+
+-- a few helpers (we need to keep 'm in sync with context) .. some day components
+-- might go so here we isolate them
+
+local setprev = nuts.setprev
+local setnext = nuts.setnext
+local getnext = nuts.getnext
+local setlink = nuts.setlink
+local getfield = nuts.getfield
+local setfield = nuts.setfield
+local getcomponents = nuts.getcomponents
+local setcomponents = nuts.setcomponents
+
+local find_tail = nuts.tail
+local flush_list = nuts.flush_list
+local flush_node = nuts.flush_node
+local traverse_id = nuts.traverse_id
+local copy_node = nuts.copy_node
+
+local glyph_code = nodes.nodecodes.glyph
+
+function nuts.set_components(target,start,stop)
+ local head = getcomponents(target)
+ if head then
+ flush_list(head)
+ head = nil
+ end
+ if start then
+ setprev(start)
+ else
+ return nil
+ end
+ if stop then
+ setnext(stop)
+ end
+ local tail = nil
+ while start do
+ local c = getcomponents(start)
+ local n = getnext(start)
+ if c then
+ if head then
+ setlink(tail,c)
+ else
+ head = c
+ end
+ tail = find_tail(c)
+ setcomponents(start)
+ flush_node(start)
+ else
+ if head then
+ setlink(tail,start)
+ else
+ head = start
+ end
+ tail = start
+ end
+ start = n
+ end
+ setcomponents(target,head)
+ -- maybe also upgrade the subtype but we don't use it anyway
+ return head
+end
+
+nuts.get_components = nuts.getcomponents
+
+function nuts.take_components(target)
+ local c = getcomponents(target)
+ setcomponents(target)
+ -- maybe also upgrade the subtype but we don't use it anyway
+ return c
+end
+
+function nuts.count_components(n,marks)
+ local components = getcomponents(n)
+ if components then
+ if marks then
+ local i = 0
+ for g in traverse_id(glyph_code,components) do
+ if not marks[getchar(g)] then
+ i = i + 1
+ end
+ end
+ return i
+ else
+ return count(glyph_code,components)
+ end
+ else
+ return 0
+ end
+end
+
+function nuts.copy_no_components(g,copyinjection)
+ local components = getcomponents(g)
+ if components then
+ setcomponents(g)
+ local n = copy_node(g)
+ if copyinjection then
+ copyinjection(n,g)
+ end
+ setcomponents(g,components)
+ -- maybe also upgrade the subtype but we don't use it anyway
+ return n
+ else
+ local n = copy_node(g)
+ if copyinjection then
+ copyinjection(n,g)
+ end
+ return n
+ end
+end
+
+function nuts.copy_only_glyphs(current)
+ local head = nil
+ local previous = nil
+ for n in traverse_id(glyph_code,current) do
+ n = copy_node(n)
+ if head then
+ setlink(previous,n)
+ else
+ head = n
+ end
+ previous = n
+ end
+ return head
+end
diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua
index 3a4a70c62..8ececb5a9 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 : 01/27/17 14:39:39
+-- merge date : 02/17/17 10:17:41
do -- begin closure to overcome local limits and interference
@@ -108,6 +108,18 @@ if flush then
local spawn=os.spawn if spawn then function os.spawn (...) flush() return spawn (...) end end
local popen=io.popen if popen then function io.popen (...) flush() return popen (...) end end
end
+if ffi and ffi.number then
+else
+ local okay
+ okay,ffi=pcall(require,"ffi")
+ if not ffi then
+ elseif ffi.os=="" or ffi.arch=="" then
+ ffi=nil
+ elseif ffi.number then
+ else
+ ffi.number=tonumber
+ end
+end
end -- closure
@@ -678,27 +690,7 @@ function lpeg.append(list,pp,delayed,checked)
end
local p_false=P(false)
local p_true=P(true)
-local function make(t)
- local function making(t)
- local p=p_false
- local keys=sortedkeys(t)
- for i=1,#keys do
- local k=keys[i]
- if k~="" then
- local v=t[k]
- if v==true then
- p=p+P(k)*p_true
- elseif v==false then
- else
- p=p+P(k)*making(v)
- end
- end
- end
- if t[""] then
- p=p+p_true
- end
- return p
- end
+local function make(t,rest)
local p=p_false
local keys=sortedkeys(t)
for i=1,#keys do
@@ -709,10 +701,13 @@ local function make(t)
p=p+P(k)*p_true
elseif v==false then
else
- p=p+P(k)*making(v)
+ p=p+P(k)*make(v,v[""])
end
end
end
+ if rest then
+ p=p+p_true
+ end
return p
end
local function collapse(t,x)
@@ -3491,6 +3486,23 @@ function utf.chrlen(u)
(u<0xFC and 5) or
(u<0xFE and 6) or 0
end
+local extract=bit32.extract
+local char=string.char
+function unicode.toutf32string(n)
+ if n<=0xFF then
+ return
+ char(n).."\000\000\000"
+ elseif n<=0xFFFF then
+ return
+ char(extract(n,0,8))..char(extract(n,8,8)).."\000\000"
+ elseif n<=0xFFFFFF then
+ return
+ char(extract(n,0,8))..char(extract(n,8,8))..char(extract(n,16,8)).."\000"
+ else
+ return
+ char(extract(n,0,8))..char(extract(n,8,8))..char(extract(n,16,8))..char(extract(n,24,8))
+ end
+end
end -- closure
@@ -4296,6 +4308,14 @@ function files.readinteger2(f)
return n
end
end
+ function files.readinteger2(f)
+ local a,b=byte(f:read(2),1,2)
+ if a>=0x80 then
+ return 0x100*a+b-0x10000
+ else
+ return 0x100*a+b
+ end
+ end
function files.readinteger2le(f)
local b,a=byte(f:read(2),1,2)
local n=0x100*a+b
@@ -4348,6 +4368,14 @@ function files.readinteger4(f)
return n
end
end
+ function files.readinteger4(f)
+ local a,b,c,d=byte(f:read(4),1,4)
+ if a>=0x80 then
+ return 0x1000000*a+0x10000*b+0x100*c+d-0x100000000
+ else
+ return 0x1000000*a+0x10000*b+0x100*c+d
+ end
+ end
function files.readinteger4le(f)
local d,c,b,a=byte(f:read(4),1,4)
local n=0x1000000*a+0x10000*b+0x100*c+d
@@ -4969,16 +4997,37 @@ nuts.setattr=setfield
nuts.getfont=direct.getfont
nuts.setfont=direct.setfont
nuts.getsubtype=direct.getsubtype
-nuts.setsubtype=direct.setsubtype or function(n,s) setfield(n,"subtype",s) end
+nuts.setsubtype=direct.setsubtype
nuts.getchar=direct.getchar
nuts.setchar=direct.setchar
nuts.getdisc=direct.getdisc
nuts.setdisc=direct.setdisc
nuts.setlink=direct.setlink
nuts.getlist=direct.getlist
-nuts.setlist=direct.setlist or function(n,l) setfield(n,"list",l) end
-nuts.getleader=direct.getleader
-nuts.setleader=direct.setleader or function(n,l) setfield(n,"leader",l) end
+nuts.setlist=direct.setlist
+nuts.getoffsets=direct.getoffsets or
+ function(n)
+ return getfield(n,"xoffset"),getfield(n,"yoffset")
+ end
+nuts.setoffsets=direct.setoffsets or
+ function(n,x,y)
+ if x then setfield(n,"xoffset",x) end
+ if y then setfield(n,"xoffset",y) end
+ end
+nuts.getleader=direct.getleader or function(n) return getfield(n,"leader") end
+nuts.setleader=direct.setleader or function(n,l) setfield(n,"leader",l) end
+nuts.getcomponents=direct.getcomponents or function(n) return getfield(n,"components") end
+nuts.setcomponents=direct.setcomponents or function(n,c) setfield(n,"components",c) end
+nuts.getkern=direct.getkern or function(n) return getfield(n,"kern") end
+nuts.setkern=direct.setkern or function(n,k) setfield(n,"kern",k) end
+nuts.getdir=direct.getkern or function(n) return getfield(n,"dir") end
+nuts.setdir=direct.setkern or function(n,d) setfield(n,"dir",d) end
+nuts.getwidth=direct.getwidth or function(n) return getfield(n,"width") end
+nuts.setwidth=direct.setwidth or function(n,w) return setfield(n,"width",w) end
+nuts.getheight=direct.getheight or function(n) return getfield(n,"height") end
+nuts.setheight=direct.setheight or function(n,h) return setfield(n,"height",h) end
+nuts.getdepth=direct.getdepth or function(n) return getfield(n,"depth") end
+nuts.setdepth=direct.setdepth or function(n,d) return setfield(n,"depth",d) end
if not direct.is_glyph then
local getchar=direct.getchar
local getid=direct.getid
@@ -5066,6 +5115,116 @@ nuts.setprop=function(n,k,v)
end
nodes.setprop=nodes.setproperty
nodes.getprop=nodes.getproperty
+local setprev=nuts.setprev
+local setnext=nuts.setnext
+local getnext=nuts.getnext
+local setlink=nuts.setlink
+local getfield=nuts.getfield
+local setfield=nuts.setfield
+local getcomponents=nuts.getcomponents
+local setcomponents=nuts.setcomponents
+local find_tail=nuts.tail
+local flush_list=nuts.flush_list
+local flush_node=nuts.flush_node
+local traverse_id=nuts.traverse_id
+local copy_node=nuts.copy_node
+local glyph_code=nodes.nodecodes.glyph
+function nuts.set_components(target,start,stop)
+ local head=getcomponents(target)
+ if head then
+ flush_list(head)
+ head=nil
+ end
+ if start then
+ setprev(start)
+ else
+ return nil
+ end
+ if stop then
+ setnext(stop)
+ end
+ local tail=nil
+ while start do
+ local c=getcomponents(start)
+ local n=getnext(start)
+ if c then
+ if head then
+ setlink(tail,c)
+ else
+ head=c
+ end
+ tail=find_tail(c)
+ setcomponents(start)
+ flush_node(start)
+ else
+ if head then
+ setlink(tail,start)
+ else
+ head=start
+ end
+ tail=start
+ end
+ start=n
+ end
+ setcomponents(target,head)
+ return head
+end
+nuts.get_components=nuts.getcomponents
+function nuts.take_components(target)
+ local c=getcomponents(target)
+ setcomponents(target)
+ return c
+end
+function nuts.count_components(n,marks)
+ local components=getcomponents(n)
+ if components then
+ if marks then
+ local i=0
+ for g in traverse_id(glyph_code,components) do
+ if not marks[getchar(g)] then
+ i=i+1
+ end
+ end
+ return i
+ else
+ return count(glyph_code,components)
+ end
+ else
+ return 0
+ end
+end
+function nuts.copy_no_components(g,copyinjection)
+ local components=getcomponents(g)
+ if components then
+ setcomponents(g)
+ local n=copy_node(g)
+ if copyinjection then
+ copyinjection(n,g)
+ end
+ setcomponents(g,components)
+ return n
+ else
+ local n=copy_node(g)
+ if copyinjection then
+ copyinjection(n,g)
+ end
+ return n
+ end
+end
+function nuts.copy_only_glyphs(current)
+ local head=nil
+ local previous=nil
+ for n in traverse_id(glyph_code,current) do
+ n=copy_node(n)
+ if head then
+ setlink(previous,n)
+ else
+ head=n
+ end
+ previous=n
+ end
+ return head
+end
end -- closure
@@ -12885,6 +13044,7 @@ do
sublookuplist[nofsublookups]=copy(h)
sublookuphash[lookupid]=nofsublookups
sublookupcheck[lookupid]=1
+ h=nofsublookups
else
report_issue(i,what,sequence,"missing")
rule.lookups=nil
@@ -15600,7 +15760,7 @@ if not modules then modules={} end modules ['font-otl']={
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files",
}
-local gmatch,find,match,lower,strip=string.gmatch,string.find,string.match,string.lower,string.strip
+local lower=string.lower
local type,next,tonumber,tostring,unpack=type,next,tonumber,tostring,unpack
local abs=math.abs
local derivetable=table.derive
@@ -15667,26 +15827,6 @@ function otf.load(filename,sub,featurefile)
hash=hash.."-"..sub
end
hash=containers.cleanname(hash)
- local featurefiles
- if featurefile then
- featurefiles={}
- for s in gmatch(featurefile,"[^,]+") do
- local name=resolvers.findfile(file.addsuffix(s,'fea'),'fea') or ""
- if name=="" then
- report_otf("loading error, no featurefile %a",s)
- else
- local attr=lfs.attributes(name)
- featurefiles[#featurefiles+1]={
- name=name,
- size=attr and attr.size or 0,
- time=attr and attr.modification or 0,
- }
- end
- end
- if #featurefiles==0 then
- featurefiles=nil
- end
- end
local data=containers.read(otf.cache,hash)
local reload=not data or data.size~=size or data.time~=time or data.tableversion~=otfreaders.tableversion
if forceload then
@@ -15753,6 +15893,17 @@ function otf.load(filename,sub,featurefile)
applyruntimefixes(filename,data)
end
data.metadata.math=data.resources.mathconstants
+ local classes=data.resources.classes
+ if not classes then
+ local descriptions=data.descriptions
+ classes=setmetatableindex(function(t,k)
+ local d=descriptions[k]
+ local v=(d and d.class or "base") or false
+ t[k]=v
+ return v
+ end)
+ data.resources.classes=classes
+ end
end
return data
end
@@ -16631,7 +16782,6 @@ local trace_injections=false registertracker("fonts.injections",function(v) trac
local trace_marks=false registertracker("fonts.injections.marks",function(v) trace_marks=v end)
local trace_cursive=false registertracker("fonts.injections.cursive",function(v) trace_cursive=v end)
local trace_spaces=false registertracker("fonts.injections.spaces",function(v) trace_spaces=v end)
-local use_advance=false directives.register("fonts.injections.advance",function(v) use_advance=v end)
local report_injections=logs.reporter("fonts","injections")
local report_spaces=logs.reporter("fonts","spaces")
local attributes,nodes,node=attributes,nodes,node
@@ -16659,12 +16809,18 @@ local getnext=nuts.getnext
local getprev=nuts.getprev
local getid=nuts.getid
local getfont=nuts.getfont
-local getsubtype=nuts.getsubtype
local getchar=nuts.getchar
+local getoffsets=nuts.getoffsets
local getboth=nuts.getboth
-local ischar=nuts.is_char
local getdisc=nuts.getdisc
local setdisc=nuts.setdisc
+local setoffsets=nuts.setoffsets
+local ischar=nuts.is_char
+local getkern=nuts.getkern
+local setkern=nuts.setkern
+local setlink=nuts.setlink
+local setwidth=nuts.setwidth
+local getwidth=nuts.getwidth
local traverse_id=nuts.traverse_id
local traverse_char=nuts.traverse_char
local insert_node_before=nuts.insert_before
@@ -16706,7 +16862,7 @@ function injections.copy(target,source)
if tp then
tp.injections=si
else
- propertydata[target]={
+ properties[target]={
injections=si,
}
end
@@ -17035,11 +17191,12 @@ local function show_result(head)
while current do
local id=getid(current)
if id==glyph_code then
- report_injections("char: %C, width %p, xoffset %p, yoffset %p",
- getchar(current),getfield(current,"width"),getfield(current,"xoffset"),getfield(current,"yoffset"))
+ local w=getwidth(current)
+ local x,y=getoffsets(current)
+ report_injections("char: %C, width %p, xoffset %p, yoffset %p",getchar(current),w,x,y)
skipping=false
elseif id==kern_code then
- report_injections("kern: %p",getfield(current,"kern"))
+ report_injections("kern: %p",getkern(current))
skipping=false
elseif not skipping then
report_injections()
@@ -17065,70 +17222,58 @@ local function inject_kerns_only(head,where)
local posttail=nil
local replacetail=nil
while current do
- local id=getid(current)
local next=getnext(current)
- if id==glyph_code then
- if getsubtype(current)<256 then
- local p=rawget(properties,current)
- if p then
- local i=p.injections
- if i then
- local leftkern=i.leftkern
- if leftkern and leftkern~=0 then
- if use_advance then
- setfield(current,"xoffset",leftkern)
- setfield(current,"xadvance",leftkern)
- else
- insert_node_before(head,current,newkern(leftkern))
+ local char,id=ischar(current)
+ if char then
+ local p=rawget(properties,current)
+ if p then
+ local i=p.injections
+ if i then
+ local leftkern=i.leftkern
+ if leftkern and leftkern~=0 then
+ insert_node_before(head,current,newkern(leftkern))
+ end
+ end
+ if prevdisc then
+ local done=false
+ if post then
+ local i=p.postinjections
+ if i then
+ local leftkern=i.leftkern
+ if leftkern and leftkern~=0 then
+ setlink(posttail,newkern(leftkern))
+ done=true
end
end
end
- if prevdisc then
- local done=false
- if post then
- local i=p.postinjections
- if i then
- local leftkern=i.leftkern
- if leftkern and leftkern~=0 then
- if use_advance then
- setfield(post,"xadvance",leftkern)
- else
- insert_node_after(post,posttail,newkern(leftkern))
- done=true
- end
- end
+ if replace then
+ local i=p.replaceinjections
+ if i then
+ local leftkern=i.leftkern
+ if leftkern and leftkern~=0 then
+ setlink(replacetail,newkern(leftkern))
+ done=true
end
end
- if replace then
- local i=p.replaceinjections
- if i then
- local leftkern=i.leftkern
- if leftkern and leftkern~=0 then
- if use_advance then
- setfield(replace,"xadvance",leftkern)
- else
- insert_node_after(replace,replacetail,newkern(leftkern))
- done=true
- end
- end
- end
- else
- local i=p.emptyinjections
- if i then
- local leftkern=i.leftkern
- if leftkern and leftkern~=0 then
- setfield(prev,"replace",newkern(leftkern))
- end
+ else
+ local i=p.emptyinjections
+ if i then
+ local leftkern=i.leftkern
+ if leftkern and leftkern~=0 then
+ setfield(prev,"replace",newkern(leftkern))
end
end
- if done then
- setdisc(prevdisc,pre,post,replace)
- end
+ end
+ if done then
+ setdisc(prevdisc,pre,post,replace)
end
end
end
prevdisc=nil
prevglyph=current
+ elseif char==false then
+ prevdisc=nil
+ prevglyph=current
elseif id==disc_code then
pre,post,replace,pretail,posttail,replacetail=getdisc(current,true)
local done=false
@@ -17140,13 +17285,8 @@ local function inject_kerns_only(head,where)
if i then
local leftkern=i.leftkern
if leftkern and leftkern~=0 then
- if use_advance then
- setfield(pre,"xoffset",leftkern)
- setfield(pre,"xadvance",leftkern)
- else
- pre=insert_node_before(pre,n,newkern(leftkern))
- done=true
- end
+ pre=insert_node_before(pre,n,newkern(leftkern))
+ done=true
end
end
end
@@ -17160,13 +17300,8 @@ local function inject_kerns_only(head,where)
if i then
local leftkern=i.leftkern
if leftkern and leftkern~=0 then
- if use_advance then
- setfield(post,"xoffset",leftkern)
- setfield(post,"xadvance",leftkern)
- else
- post=insert_node_before(post,n,newkern(leftkern))
- done=true
- end
+ post=insert_node_before(post,n,newkern(leftkern))
+ done=true
end
end
end
@@ -17180,13 +17315,8 @@ local function inject_kerns_only(head,where)
if i then
local leftkern=i.leftkern
if leftkern and leftkern~=0 then
- if use_advance then
- setfield(replace,"xoffset",leftkern)
- setfield(replace,"xadvance",leftkern)
- else
- replace=insert_node_before(replace,n,newkern(leftkern))
- done=true
- end
+ replace=insert_node_before(replace,n,newkern(leftkern))
+ done=true
end
end
end
@@ -17228,78 +17358,79 @@ local function inject_pairs_only(head,where)
local posttail=nil
local replacetail=nil
while current do
- local id=getid(current)
local next=getnext(current)
- if id==glyph_code then
- if getsubtype(current)<256 then
- local p=rawget(properties,current)
- if p then
- local i=p.injections
+ local char,id=ischar(current)
+ if char then
+ local p=rawget(properties,current)
+ if p then
+ local i=p.injections
+ if i then
+ local yoffset=i.yoffset
+ if yoffset and yoffset~=0 then
+ setoffsets(current,false,yoffset)
+ end
+ local leftkern=i.leftkern
+ if leftkern and leftkern~=0 then
+ head=insert_node_before(head,current,newkern(leftkern))
+ end
+ local rightkern=i.rightkern
+ if rightkern and rightkern~=0 then
+ insert_node_after(head,current,newkern(rightkern))
+ end
+ else
+ local i=p.emptyinjections
if i then
- local yoffset=i.yoffset
- if yoffset and yoffset~=0 then
- setfield(current,"yoffset",yoffset)
- end
- local leftkern=i.leftkern
- if leftkern and leftkern~=0 then
- head=insert_node_before(head,current,newkern(leftkern))
- end
local rightkern=i.rightkern
if rightkern and rightkern~=0 then
- insert_node_after(head,current,newkern(rightkern))
- end
- else
- local i=p.emptyinjections
- if i then
- local rightkern=i.rightkern
- if rightkern and rightkern~=0 then
- if next and getid(next)==disc_code then
- if replace then
- else
- setfield(next,"replace",newkern(rightkern))
- end
+ if next and getid(next)==disc_code then
+ if replace then
+ else
+ setfield(next,"replace",newkern(rightkern))
end
end
end
end
- if prevdisc then
- local done=false
- if post then
- local i=p.postinjections
- if i then
- local leftkern=i.leftkern
- if leftkern and leftkern~=0 then
- insert_node_after(post,posttail,newkern(leftkern))
- done=true
- end
+ end
+ if prevdisc then
+ local done=false
+ if post then
+ local i=p.postinjections
+ if i then
+ local leftkern=i.leftkern
+ if leftkern and leftkern~=0 then
+ setlink(posttail,newkern(leftkern))
+ done=true
end
end
- if replace then
- local i=p.replaceinjections
- if i then
- local leftkern=i.leftkern
- if leftkern and leftkern~=0 then
- insert_node_after(replace,replacetail,newkern(leftkern))
- done=true
- end
- end
- else
- local i=p.emptyinjections
- if i then
- local leftkern=i.leftkern
- if leftkern and leftkern~=0 then
- setfield(prev,"replace",newkern(leftkern))
- end
+ end
+ if replace then
+ local i=p.replaceinjections
+ if i then
+ local leftkern=i.leftkern
+ if leftkern and leftkern~=0 then
+ setlink(replacetail,newkern(leftkern))
+ done=true
end
end
- if done then
- setdisc(prevdisc,pre,post,replace)
+ else
+ local i=p.emptyinjections
+ if i then
+ local leftkern=i.leftkern
+ if leftkern and leftkern~=0 then
+ setfield(prev,"replace",newkern(leftkern))
+ end
end
end
+ if done then
+ setdisc(prevdisc,pre,post,replace)
+ end
end
end
prevdisc=nil
prevglyph=current
+ elseif char==false then
+ prevdisc=nil
+ prevglyph=current
elseif id==disc_code then
pre,post,replace,pretail,posttail,replacetail=getdisc(current,true)
local done=false
@@ -17311,7 +17442,7 @@ local function inject_pairs_only(head,where)
if i then
local yoffset=i.yoffset
if yoffset and yoffset~=0 then
- setfield(n,"yoffset",yoffset)
+ setoffsets(n,false,yoffset)
end
local leftkern=i.leftkern
if leftkern and leftkern~=0 then
@@ -17335,7 +17466,7 @@ local function inject_pairs_only(head,where)
if i then
local yoffset=i.yoffset
if yoffset and yoffset~=0 then
- setfield(n,"yoffset",yoffset)
+ setoffsets(n,false,yoffset)
end
local leftkern=i.leftkern
if leftkern and leftkern~=0 then
@@ -17359,7 +17490,7 @@ local function inject_pairs_only(head,where)
if i then
local yoffset=i.yoffset
if yoffset and yoffset~=0 then
- setfield(n,"yoffset",yoffset)
+ setoffsets(n,false,yoffset)
end
local leftkern=i.leftkern
if leftkern and leftkern~=0 then
@@ -17423,11 +17554,8 @@ local function inject_pairs_only(head,where)
return tonode(head),true
end
local function showoffset(n,flag)
- local o=getfield(n,"xoffset")
- if o==0 then
- o=getfield(n,"yoffset")
- end
- if o~=0 then
+ local x,y=getoffsets(n)
+ if x~=0 or y~=0 then
setcolor(n,flag and "darkred" or "darkgreen")
else
resetcolor(n)
@@ -17461,7 +17589,8 @@ local function inject_everything(head,where)
local marks={}
local nofmarks=0
local function processmark(p,n,pn)
- local px=getfield(p,"xoffset")
+ local px,py=getoffsets(p)
+ local nx,ny=getoffsets(n)
local ox=0
local rightkern=nil
local pp=rawget(properties,p)
@@ -17489,7 +17618,7 @@ local function inject_everything(head,where)
else
ox=px-pn.markx
if pn.checkmark then
- local wn=getfield(n,"width")
+ local wn=getwidth(n)
if wn~=0 then
wn=wn/2
if trace_injections then
@@ -17500,156 +17629,157 @@ local function inject_everything(head,where)
end
end
end
- local oy=getfield(n,"yoffset")+getfield(p,"yoffset")+pn.marky
- setfield(n,"xoffset",ox)
- setfield(n,"yoffset",oy)
+ local oy=ny+py+pn.marky
+ setoffsets(n,ox,oy)
if trace_marks then
showoffset(n,true)
end
end
while current do
- local id=getid(current)
local next=getnext(current)
- if id==glyph_code then
- if getsubtype(current)<256 then
- local p=rawget(properties,current)
- if p then
- local i=p.injections
- if i then
- local pm=i.markbasenode
- if pm then
- nofmarks=nofmarks+1
- marks[nofmarks]=current
- else
- local yoffset=i.yoffset
- if yoffset and yoffset~=0 then
- setfield(current,"yoffset",yoffset)
- end
- if hascursives then
- local cursivex=i.cursivex
- if cursivex then
- if cursiveanchor then
- if cursivex~=0 then
- i.leftkern=(i.leftkern or 0)+cursivex
- end
- if maxc==0 then
- minc=1
- maxc=1
- glyphs[1]=cursiveanchor
- else
- maxc=maxc+1
- glyphs[maxc]=cursiveanchor
- end
- properties[cursiveanchor].cursivedy=i.cursivey
- last=current
+ local char,id=ischar(current)
+ if char then
+ local p=rawget(properties,current)
+ if p then
+ local i=p.injections
+ if i then
+ local pm=i.markbasenode
+ if pm then
+ nofmarks=nofmarks+1
+ marks[nofmarks]=current
+ else
+ local yoffset=i.yoffset
+ if yoffset and yoffset~=0 then
+ setoffsets(current,false,yoffset)
+ end
+ if hascursives then
+ local cursivex=i.cursivex
+ if cursivex then
+ if cursiveanchor then
+ if cursivex~=0 then
+ i.leftkern=(i.leftkern or 0)+cursivex
+ end
+ if maxc==0 then
+ minc=1
+ maxc=1
+ glyphs[1]=cursiveanchor
else
- maxc=0
+ maxc=maxc+1
+ glyphs[maxc]=cursiveanchor
+ end
+ properties[cursiveanchor].cursivedy=i.cursivey
+ last=current
+ else
+ maxc=0
+ end
+ elseif maxc>0 then
+ local nx,ny=getoffsets(current)
+ for i=maxc,minc,-1 do
+ local ti=glyphs[i]
+ ny=ny+properties[ti].cursivedy
+ setoffsets(ti,false,ny)
+ if trace_cursive then
+ showoffset(ti)
end
- elseif maxc>0 then
- local ny=getfield(current,"yoffset")
+ end
+ maxc=0
+ cursiveanchor=nil
+ end
+ if i.cursiveanchor then
+ cursiveanchor=current
+ else
+ if maxc>0 then
+ local nx,ny=getoffsets(current)
for i=maxc,minc,-1 do
local ti=glyphs[i]
ny=ny+properties[ti].cursivedy
- setfield(ti,"yoffset",ny)
+ setoffsets(ti,false,ny)
if trace_cursive then
showoffset(ti)
end
end
maxc=0
- cursiveanchor=nil
end
- if i.cursiveanchor then
- cursiveanchor=current
- else
- if maxc>0 then
- local ny=getfield(current,"yoffset")
- for i=maxc,minc,-1 do
- local ti=glyphs[i]
- ny=ny+properties[ti].cursivedy
- setfield(ti,"yoffset",ny)
- if trace_cursive then
- showoffset(ti)
- end
- end
- maxc=0
- end
- cursiveanchor=nil
- end
- end
- local leftkern=i.leftkern
- if leftkern and leftkern~=0 then
- insert_node_before(head,current,newkern(leftkern))
- end
- local rightkern=i.rightkern
- if rightkern and rightkern~=0 then
- insert_node_after(head,current,newkern(rightkern))
+ cursiveanchor=nil
end
end
- else
- local i=p.emptyinjections
- if i then
- local rightkern=i.rightkern
- if rightkern and rightkern~=0 then
- if next and getid(next)==disc_code then
- if replace then
- else
- setfield(next,"replace",newkern(rightkern))
- end
+ local leftkern=i.leftkern
+ if leftkern and leftkern~=0 then
+ insert_node_before(head,current,newkern(leftkern))
+ end
+ local rightkern=i.rightkern
+ if rightkern and rightkern~=0 then
+ insert_node_after(head,current,newkern(rightkern))
+ end
+ end
+ else
+ local i=p.emptyinjections
+ if i then
+ local rightkern=i.rightkern
+ if rightkern and rightkern~=0 then
+ if next and getid(next)==disc_code then
+ if replace then
+ else
+ setfield(next,"replace",newkern(rightkern))
end
end
end
end
- if prevdisc then
- if p then
- local done=false
- if post then
- local i=p.postinjections
- if i then
- local leftkern=i.leftkern
- if leftkern and leftkern~=0 then
- insert_node_after(post,posttail,newkern(leftkern))
- done=true
- end
+ end
+ if prevdisc then
+ if p then
+ local done=false
+ if post then
+ local i=p.postinjections
+ if i then
+ local leftkern=i.leftkern
+ if leftkern and leftkern~=0 then
+ setlink(posttail,newkern(leftkern))
+ done=true
end
end
- if replace then
- local i=p.replaceinjections
- if i then
- local leftkern=i.leftkern
- if leftkern and leftkern~=0 then
- insert_node_after(replace,replacetail,newkern(leftkern))
- done=true
- end
- end
- else
- local i=p.emptyinjections
- if i then
- local leftkern=i.leftkern
- if leftkern and leftkern~=0 then
- setfield(prev,"replace",newkern(leftkern))
- end
+ end
+ if replace then
+ local i=p.replaceinjections
+ if i then
+ local leftkern=i.leftkern
+ if leftkern and leftkern~=0 then
+ setlink(replacetail,newkern(leftkern))
+ done=true
end
end
- if done then
- setdisc(prevdisc,pre,post,replace)
+ else
+ local i=p.emptyinjections
+ if i then
+ local leftkern=i.leftkern
+ if leftkern and leftkern~=0 then
+ setfield(prev,"replace",newkern(leftkern))
+ end
end
end
- end
- else
- if hascursives and maxc>0 then
- local ny=getfield(current,"yoffset")
- for i=maxc,minc,-1 do
- local ti=glyphs[i]
- ny=ny+properties[ti].cursivedy
- setfield(ti,"yoffset",getfield(ti,"yoffset")+ny)
+ if done then
+ setdisc(prevdisc,pre,post,replace)
end
- maxc=0
- cursiveanchor=nil
end
end
+ else
+ if hascursives and maxc>0 then
+ local nx,ny=getoffsets(current)
+ for i=maxc,minc,-1 do
+ local ti=glyphs[i]
+ ny=ny+properties[ti].cursivedy
+ local xi,yi=getoffsets(ti)
+ setoffsets(ti,xi,yi+ny)
+ end
+ maxc=0
+ cursiveanchor=nil
+ end
end
prevdisc=nil
prevglyph=current
+ elseif char==false then
+ prevdisc=nil
+ prevglyph=current
elseif id==disc_code then
pre,post,replace,pretail,posttail,replacetail=getdisc(current,true)
local done=false
@@ -17661,7 +17791,7 @@ local function inject_everything(head,where)
if i then
local yoffset=i.yoffset
if yoffset and yoffset~=0 then
- setfield(n,"yoffset",yoffset)
+ setoffsets(n,false,yoffset)
end
local leftkern=i.leftkern
if leftkern and leftkern~=0 then
@@ -17691,7 +17821,7 @@ local function inject_everything(head,where)
if i then
local yoffset=i.yoffset
if yoffset and yoffset~=0 then
- setfield(n,"yoffset",yoffset)
+ setoffsets(n,false,yoffset)
end
local leftkern=i.leftkern
if leftkern and leftkern~=0 then
@@ -17721,7 +17851,7 @@ local function inject_everything(head,where)
if i then
local yoffset=i.yoffset
if yoffset and yoffset~=0 then
- setfield(n,"yoffset",yoffset)
+ setoffsets(n,false,yoffset)
end
local leftkern=i.leftkern
if leftkern and leftkern~=0 then
@@ -17784,11 +17914,11 @@ local function inject_everything(head,where)
current=next
end
if hascursives and maxc>0 then
- local ny=getfield(last,"yoffset")
+ local nx,ny=getoffsets(last)
for i=maxc,minc,-1 do
local ti=glyphs[i]
ny=ny+properties[ti].cursivedy
- setfield(ti,"yoffset",ny)
+ setoffsets(ti,false,ny)
if trace_cursive then
showoffset(ti)
end
@@ -17845,9 +17975,9 @@ else
end
end
injections.getthreshold=getthreshold
-function injections.isspace(n,threshold)
- if getid(n)==glue_code then
- local w=getfield(n,"width")
+function injections.isspace(n,threshold,id)
+ if (id or getid(n))==glue_code then
+ local w=getwidth(n)
if threshold and w>threshold then
return 32
end
@@ -17901,32 +18031,32 @@ local function injectspaces(head)
end
end
if leftkern then
- local old=getfield(n,"width")
+ local old=getwidth(n)
if old>threshold then
if rightkern then
local new=old+(leftkern+rightkern)*factor
if trace_spaces then
report_spaces("%C [%p -> %p] %C",prevchar,old,new,nextchar)
end
- setfield(n,"width",new)
+ setwidth(n,new)
leftkern=false
else
local new=old+leftkern*factor
if trace_spaces then
report_spaces("%C [%p -> %p]",prevchar,old,new)
end
- setfield(n,"width",new)
+ setwidth(n,new)
end
end
leftkern=false
elseif rightkern then
- local old=getfield(n,"width")
+ local old=getwidth(n)
if old>threshold then
local new=old+rightkern*factor
if trace_spaces then
report_spaces("[%p -> %p] %C",nextchar,old,new)
end
- setfield(n,"width",new)
+ setwidth(n,new)
end
rightkern=false
end
@@ -17982,7 +18112,6 @@ analyzers.methods=methods
local a_state=attributes.private('state')
local nuts=nodes.nuts
local tonut=nuts.tonut
-local getfield=nuts.getfield
local getnext=nuts.getnext
local getprev=nuts.getprev
local getprev=nuts.getprev
@@ -18355,11 +18484,14 @@ local type,next,tonumber=type,next,tonumber
local random=math.random
local formatters=string.formatters
local insert=table.insert
-local logs,trackers,nodes,attributes=logs,trackers,nodes,attributes
local registertracker=trackers.register
-local registerdirective=directives.register
+local logs=logs
+local trackers=trackers
+local nodes=nodes
+local attributes=attributes
local fonts=fonts
local otf=fonts.handlers.otf
+local tracers=nodes.tracers
local trace_lookups=false registertracker("otf.lookups",function(v) trace_lookups=v end)
local trace_singles=false registertracker("otf.singles",function(v) trace_singles=v end)
local trace_multiples=false registertracker("otf.multiples",function(v) trace_multiples=v end)
@@ -18381,7 +18513,6 @@ local trace_discruns=false registertracker("otf.discruns",function(v) trace_disc
local trace_compruns=false registertracker("otf.compruns",function(v) trace_compruns=v end)
local trace_testruns=false registertracker("otf.testruns",function(v) trace_testruns=v end)
local optimizekerns=true
-local alwaysdisc=true registerdirective("otf.alwaysdisc",function(v) alwaysdisc=v end)
local report_direct=logs.reporter("fonts","otf direct")
local report_subchain=logs.reporter("fonts","otf subchain")
local report_chain=logs.reporter("fonts","otf chain")
@@ -18392,7 +18523,7 @@ registertracker("otf.replacements","otf.singles,otf.multiples,otf.alternatives,o
registertracker("otf.positions","otf.marks,otf.kerns,otf.cursive")
registertracker("otf.actions","otf.replacements,otf.positions")
registertracker("otf.injections","nodes.injections")
-registertracker("*otf.sample","otf.steps,otf.actions,otf.analyzing")
+registertracker("otf.sample","otf.steps,otf.actions,otf.analyzing")
local nuts=nodes.nuts
local tonode=nuts.tonode
local tonut=nuts.tonut
@@ -18417,6 +18548,10 @@ local setchar=nuts.setchar
local getdisc=nuts.getdisc
local setdisc=nuts.setdisc
local setlink=nuts.setlink
+local getcomponents=nuts.getcomponents
+local setcomponents=nuts.setcomponents
+local getdir=nuts.getdir
+local getwidth=nuts.getwidth
local ischar=nuts.is_char
local insert_node_after=nuts.insert_after
local copy_node=nuts.copy
@@ -18427,12 +18562,12 @@ local flush_node=nuts.flush_node
local end_of_math=nuts.end_of_math
local traverse_nodes=nuts.traverse
local traverse_id=nuts.traverse_id
-local remove_node=nuts.remove
+local set_components=nuts.set_components
+local take_components=nuts.take_components
+local count_components=nuts.count_components
+local copy_no_components=nuts.copy_no_components
+local copy_only_glyphs=nuts.copy_only_glyphs
local setmetatableindex=table.setmetatableindex
-local zwnj=0x200C
-local zwj=0x200D
-local wildcard="*"
-local default="dflt"
local nodecodes=nodes.nodecodes
local glyphcodes=nodes.glyphcodes
local disccodes=nodes.disccodes
@@ -18446,6 +18581,7 @@ local discretionary_code=disccodes.discretionary
local ligature_code=glyphcodes.ligature
local privateattribute=attributes.private
local a_state=privateattribute('state')
+local a_noligature=privateattribute("noligature")
local injections=nodes.injections
local setmark=injections.setmark
local setcursive=injections.setcursive
@@ -18455,10 +18591,8 @@ local resetinjection=injections.reset
local copyinjection=injections.copy
local setligaindex=injections.setligaindex
local getligaindex=injections.getligaindex
-local cursonce=true
-local fonthashes=fonts.hashes
-local fontdata=fonthashes.identifiers
-local fontfeatures=fonthashes.features
+local fontdata=fonts.hashes.identifiers
+local fontfeatures=fonts.hashes.features
local otffeatures=fonts.constructors.features.otf
local registerotffeature=otffeatures.register
local onetimemessage=fonts.loggers.onetimemessage or function() end
@@ -18468,6 +18602,7 @@ local tfmdata=false
local characters=false
local descriptions=false
local marks=false
+local classes=false
local currentfont=false
local factor=0
local threshold=0
@@ -18482,9 +18617,9 @@ local notmatchreplace={}
local handlers={}
local isspace=injections.isspace
local getthreshold=injections.getthreshold
-local checkstep=(nodes and nodes.tracers and nodes.tracers.steppers.check) or function() end
-local registerstep=(nodes and nodes.tracers and nodes.tracers.steppers.register) or function() end
-local registermessage=(nodes and nodes.tracers and nodes.tracers.steppers.message) or function() end
+local checkstep=(tracers and tracers.steppers.check) or function() end
+local registerstep=(tracers and tracers.steppers.register) or function() end
+local registermessage=(tracers and tracers.steppers.message) or function() end
local function checkdisccontent(d)
local pre,post,replace=getdisc(d)
if pre then for n in traverse_id(glue_code,pre) do print("pre",nodes.idstostring(pre)) break end end
@@ -18548,20 +18683,6 @@ local function mref(rlmode)
return "l2r"
end
end
-local function copy_glyph(g)
- local components=getfield(g,"components")
- if components then
- setfield(g,"components")
- local n=copy_node(g)
- copyinjection(n,g)
- setfield(g,"components",components)
- return n
- else
- local n=copy_node(g)
- copyinjection(n,g)
- return n
- end
-end
local function flattendisk(head,disc)
local pre,post,replace,pretail,posttail,replacetail=getdisc(disc,true)
local prev,next=getboth(disc)
@@ -18605,15 +18726,34 @@ local function appenddisc(disc,list)
if post then
setlink(posttail,posthead)
else
- post=phead
+ post=posthead
end
if replace then
setlink(replacetail,replacehead)
else
- replace=rhead
+ replace=replacehead
end
setdisc(disc,pre,post,replace)
end
+local take_components=getcomponents
+local set_components=setcomponents
+local function count_components(start,marks)
+ if getid(start)~=glyph_code then
+ return 0
+ elseif getsubtype(start)==ligature_code then
+ local i=0
+ local components=getcomponents(start)
+ while components do
+ i=i+count_components(components,marks)
+ components=getnext(components)
+ end
+ return i
+ elseif not marks[getchar(start)] then
+ return 1
+ else
+ return 0
+ end
+end
local function markstoligature(head,start,stop,char)
if start==stop and getchar(start)==char then
return head,start
@@ -18622,37 +18762,18 @@ local function markstoligature(head,start,stop,char)
local next=getnext(stop)
setprev(start)
setnext(stop)
- local base=copy_glyph(start)
+ local base=copy_no_components(start,copyinjection)
if head==start then
head=base
end
resetinjection(base)
setchar(base,char)
setsubtype(base,ligature_code)
- setfield(base,"components",start)
- setlink(prev,base)
- setlink(base,next)
+ set_components(base,start)
+ setlink(prev,base,next)
return head,base
end
end
-local function getcomponentindex(start)
- if getid(start)~=glyph_code then
- return 0
- elseif getsubtype(start)==ligature_code then
- local i=0
- local components=getfield(start,"components")
- while components do
- i=i+getcomponentindex(components)
- components=getnext(components)
- end
- return i
- elseif not marks[getchar(start)] then
- return 1
- else
- return 0
- end
-end
-local a_noligature=attributes.private("noligature")
local function toligature(head,start,stop,char,dataset,sequence,markflag,discfound)
if getattr(start,a_noligature)==1 then
return head,start
@@ -18662,29 +18783,20 @@ local function toligature(head,start,stop,char,dataset,sequence,markflag,discfou
setchar(start,char)
return head,start
end
- local components=getfield(start,"components")
- if components then
- end
local prev=getprev(start)
local next=getnext(stop)
local comp=start
setprev(start)
setnext(stop)
- local base=copy_glyph(start)
+ local base=copy_no_components(start,copyinjection)
if start==head then
head=base
end
resetinjection(base)
setchar(base,char)
setsubtype(base,ligature_code)
- setfield(base,"components",comp)
- if prev then
- setnext(prev,base)
- end
- if next then
- setprev(next,base)
- end
- setboth(base,prev,next)
+ set_components(base,comp)
+ setlink(prev,base,next)
if not discfound then
local deletemarks=markflag~="mark"
local components=start
@@ -18696,7 +18808,7 @@ local function toligature(head,start,stop,char,dataset,sequence,markflag,discfou
local char=getchar(start)
if not marks[char] then
baseindex=baseindex+componentindex
- componentindex=getcomponentindex(start)
+ componentindex=count_components(start,marks)
elseif not deletemarks then
setligaindex(start,baseindex+getligaindex(start,componentindex))
if trace_marks then
@@ -18731,27 +18843,14 @@ local function toligature(head,start,stop,char,dataset,sequence,markflag,discfou
local discprev,discnext=getboth(discfound)
if discprev and discnext then
local pre,post,replace,pretail,posttail,replacetail=getdisc(discfound,true)
- if not replace then
+ if not replace then
local prev=getprev(base)
- local current=comp
- local previous=nil
- local copied=nil
- while current do
- if getid(current)==glyph_code then
- local n=copy_node(current)
- if copied then
- setlink(previous,n)
- else
- copied=n
- end
- previous=n
- end
- current=getnext(current)
- end
- setprev(discnext)
- setnext(discprev)
+ local comp=take_components(base)
+ local copied=copy_only_glyphs(comp)
if pre then
setlink(discprev,pre)
+ else
+ setnext(discprev)
end
pre=comp
if post then
@@ -18759,13 +18858,14 @@ local function toligature(head,start,stop,char,dataset,sequence,markflag,discfou
setprev(post)
else
post=discnext
+ setprev(discnext)
end
- setlink(prev,discfound)
- setlink(discfound,next)
+ setlink(prev,discfound,next)
setboth(base)
- setfield(base,"components",copied)
- setdisc(discfound,pre,post,base)
- base=prev
+ set_components(base,copied)
+ replace=base
+ setdisc(discfound,pre,post,replace)
+ base=prev
end
end
end
@@ -18999,7 +19099,6 @@ function handlers.gpos_pair(head,start,dataset,sequence,kerns,rlmode,step,i,inje
return head,start,false
else
local prev=start
- local done=false
while snext do
local nextchar=ischar(snext,currentfont)
if nextchar then
@@ -19017,8 +19116,7 @@ function handlers.gpos_pair(head,start,dataset,sequence,kerns,rlmode,step,i,inje
if trace_kerns then
logprocess("%s: shifting single %s by %p",pref(dataset,sequence),gref(nextchar),k)
end
- done=true
- break
+ return head,start,true
end
end
if a and #a>0 then
@@ -19035,15 +19133,13 @@ function handlers.gpos_pair(head,start,dataset,sequence,kerns,rlmode,step,i,inje
logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p) as %s",pref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h,injection or "injections")
end
end
- done=true
- break
+ return head,start,true
elseif krn~=0 then
local k=setkern(snext,factor,rlmode,krn,injection)
if trace_kerns then
logprocess("%s: inserting kern %p between %s and %s as %s",pref(dataset,sequence),k,gref(getchar(prev)),gref(nextchar),injection or "injections")
end
- done=true
- break
+ return head,start,true
else
break
end
@@ -19051,7 +19147,7 @@ function handlers.gpos_pair(head,start,dataset,sequence,kerns,rlmode,step,i,inje
break
end
end
- return head,start,done
+ return head,start,false
end
end
function handlers.gpos_mark2base(head,start,dataset,sequence,markanchors,rlmode)
@@ -19204,7 +19300,6 @@ function handlers.gpos_mark2mark(head,start,dataset,sequence,markanchors,rlmode)
return head,start,false
end
function handlers.gpos_cursive(head,start,dataset,sequence,exitanchors,rlmode,step,i)
- local done=false
local startchar=getchar(start)
if marks[startchar] then
if trace_cursive then
@@ -19212,7 +19307,7 @@ function handlers.gpos_cursive(head,start,dataset,sequence,exitanchors,rlmode,st
end
else
local nxt=getnext(start)
- while not done and nxt do
+ while nxt do
local nextchar=ischar(nxt,currentfont)
if not nextchar then
break
@@ -19229,7 +19324,7 @@ function handlers.gpos_cursive(head,start,dataset,sequence,exitanchors,rlmode,st
if trace_cursive then
logprocess("%s: moving %s to %s cursive (%p,%p) using anchor %s and bound %s in %s mode",pref(dataset,sequence),gref(startchar),gref(nextchar),dx,dy,anchor,bound,mref(rlmode))
end
- done=true
+ return head,start,true
end
end
end
@@ -19237,7 +19332,7 @@ function handlers.gpos_cursive(head,start,dataset,sequence,exitanchors,rlmode,st
end
end
end
- return head,start,done
+ return head,start,false
end
local chainprocs={}
local function logprocess(...)
@@ -19279,10 +19374,11 @@ function chainprocs.gsub_single(head,start,stop,dataset,sequence,currentlookup,c
reportmoresteps(dataset,sequence)
end
local current=start
+ local mapping=steps[1].coverage
while current do
local currentchar=ischar(current)
if currentchar then
- local replacement=steps[1].coverage[currentchar]
+ local replacement=mapping[currentchar]
if not replacement or replacement=="" then
if trace_bugs then
logwarning("%s: no single for %s",cref(dataset,sequence,chainindex),gref(currentchar))
@@ -19335,10 +19431,11 @@ function chainprocs.gsub_alternate(head,start,stop,dataset,sequence,currentlooku
local what=dataset[1]
local value=what==true and tfmdata.shared.features[kind] or what
local current=start
+ local mapping=steps[1].coverage
while current do
local currentchar=ischar(current)
if currentchar then
- local alternatives=steps[1].coverage[currentchar]
+ local alternatives=mapping[currentchar]
if alternatives then
local choice,comment=get_alternative_glyph(current,alternatives,value)
if choice then
@@ -19474,7 +19571,6 @@ function chainprocs.gpos_pair(head,start,stop,dataset,sequence,currentlookup,rlm
local kerns=step.coverage[startchar]
if kerns then
local prev=start
- local done=false
while snext do
local nextchar=ischar(snext,currentfont)
if not nextchar then
@@ -19494,8 +19590,7 @@ function chainprocs.gpos_pair(head,start,stop,dataset,sequence,currentlookup,rlm
if trace_kerns then
logprocess("%s: shifting single %s by %p",cref(dataset,sequence),gref(startchar),k)
end
- done=true
- break
+ return head,start,true
end
end
if a and #a>0 then
@@ -19512,20 +19607,17 @@ function chainprocs.gpos_pair(head,start,stop,dataset,sequence,currentlookup,rlm
logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h)
end
end
- done=true
- break
+ return head,start,true
elseif krn~=0 then
local k=setkern(snext,factor,rlmode,krn)
if trace_kerns then
logprocess("%s: inserting kern %s between %s and %s",cref(dataset,sequence),k,gref(getchar(prev)),gref(nextchar))
end
- done=true
- break
+ return head,start,true
else
break
end
end
- return head,start,done
end
end
return head,start,false
@@ -19720,14 +19812,13 @@ function chainprocs.gpos_cursive(head,start,stop,dataset,sequence,currentlookup,
local startchar=getchar(start)
local exitanchors=steps[1].coverage[startchar]
if exitanchors then
- local done=false
if marks[startchar] then
if trace_cursive then
logprocess("%s: ignoring cursive for mark %s",pref(dataset,sequence),gref(startchar))
end
else
local nxt=getnext(start)
- while not done and nxt do
+ while nxt do
local nextchar=ischar(nxt,currentfont)
if not nextchar then
break
@@ -19744,8 +19835,7 @@ function chainprocs.gpos_cursive(head,start,stop,dataset,sequence,currentlookup,
if trace_cursive then
logprocess("%s: moving %s to %s cursive (%p,%p) using anchor %s and bound %s in %s mode",pref(dataset,sequence),gref(startchar),gref(nextchar),dx,dy,anchor,bound,mref(rlmode))
end
- done=true
- break
+ return head,start,true
end
end
elseif trace_bugs then
@@ -19755,13 +19845,10 @@ function chainprocs.gpos_cursive(head,start,stop,dataset,sequence,currentlookup,
end
end
end
- return head,start,done
- else
- if trace_cursive and trace_details then
- logprocess("%s, cursive %s is already done",pref(dataset,sequence),gref(getchar(start)),alreadydone)
- end
- return head,start,false
+ elseif trace_cursive and trace_details then
+ logprocess("%s, cursive %s is already done",pref(dataset,sequence),gref(getchar(start)),alreadydone)
end
+ return head,start,false
end
local function show_skip(dataset,sequence,char,ck,class)
logwarning("%s: skipping char %s, class %a, rule %a, lookuptype %a",cref(dataset,sequence),gref(char),class,ck[1],ck[8] or ck[2])
@@ -19771,7 +19858,7 @@ local function checked(head)
local current=head
while current do
if getid(current)==glue_code then
- local kern=new_kern(getfield(current,"width"))
+ local kern=new_kern(getwidth(current))
if head==current then
local next=getnext(current)
if next then
@@ -19782,8 +19869,7 @@ local function checked(head)
current=next
else
local prev,next=getboth(current)
- setlink(prev,kern)
- setlink(kern,next)
+ setlink(prev,kern,next)
flush_node(current)
current=next
end
@@ -19799,7 +19885,85 @@ local function setdiscchecked(d,pre,post,replace)
if replace then replace=checked(replace) end
setdisc(d,pre,post,replace)
end
-local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,ck,chainproc)
+local noflags={ false,false,false,false }
+local function chainrun(head,start,last,dataset,sequence,rlmode,ck,skipped)
+ local size=ck[5]-ck[4]+1
+ local flags=sequence.flags or noflags
+ local done=false
+ local skipmark=flags[1]
+ local chainlookups=ck[6]
+ if chainlookups then
+ local nofchainlookups=#chainlookups
+ if size==1 then
+ local chainlookup=chainlookups[1]
+ local chainkind=chainlookup.type
+ local chainproc=chainprocs[chainkind]
+ if chainproc then
+ local ok
+ head,start,ok=chainproc(head,start,last,dataset,sequence,chainlookup,rlmode,1)
+ if ok then
+ done=true
+ end
+ else
+ logprocess("%s: %s is not yet supported (1)",cref(dataset,sequence),chainkind)
+ end
+ else
+ local i=1
+ while start do
+ if skipped then
+ while start do
+ local char=getchar(start)
+ local class=classes[char]
+ if class then
+ if class==skipmark or class==skipligature or class==skipbase or (markclass and class=="mark" and not markclass[char]) then
+ start=getnext(start)
+ else
+ break
+ end
+ else
+ break
+ end
+ end
+ end
+ local chainlookup=chainlookups[i]
+ if chainlookup then
+ local chainkind=chainlookup.type
+ local chainproc=chainprocs[chainkind]
+ if chainproc then
+ local ok,n
+ head,start,ok,n=chainproc(head,start,last,dataset,sequence,chainlookup,rlmode,i)
+ if ok then
+ done=true
+ if n and n>1 and i+n>nofchainlookups then
+ break
+ end
+ end
+ else
+ logprocess("%s: %s is not yet supported (2)",cref(dataset,sequence),chainkind)
+ end
+ end
+ i=i+1
+ if i>size or not start then
+ break
+ elseif start then
+ start=getnext(start)
+ end
+ end
+ end
+ else
+ local replacements=ck[7]
+ if replacements then
+ head,start,done=reversesub(head,start,last,dataset,sequence,replacements,rlmode)
+ else
+ done=true
+ if trace_contexts then
+ logprocess("%s: skipping match",cref(dataset,sequence))
+ end
+ end
+ end
+ return head,start,done
+end
+local function chaindisk(head,start,dataset,sequence,rlmode,ck,skipped)
if not start then
return head,start,false
end
@@ -19812,7 +19976,6 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
local sweepnode=sweepnode
local sweeptype=sweeptype
local sweepoverflow=false
- local checkdisc=getprev(head)
local keepdisc=not sweepnode
local lookaheaddisc=nil
local backtrackdisc=nil
@@ -19835,18 +19998,22 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
elseif id==disc_code then
if keepdisc then
keepdisc=false
- if notmatchpre[current]~=notmatchreplace[current] then
- lookaheaddisc=current
- end
+ lookaheaddisc=current
local replace=getfield(current,"replace")
- while replace and i<=l do
- if getid(replace)==glyph_code then
- i=i+1
+ if not replace then
+ sweepoverflow=true
+ sweepnode=current
+ current=getnext(current)
+ else
+ while replace and i<=l do
+ if getid(replace)==glyph_code then
+ i=i+1
+ end
+ replace=getnext(replace)
end
- replace=getnext(replace)
+ current=getnext(replace)
end
last=current
- current=getnext(c)
else
head,current=flattendisk(head,current)
end
@@ -19904,7 +20071,7 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
if notmatchpre[current]~=notmatchreplace[current] then
lookaheaddisc=current
end
- local replace=getfield(c,"replace")
+ local replace=getfield(current,"replace")
while replace and i<s do
if getid(replace)==glyph_code then
i=i+1
@@ -19965,7 +20132,7 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
end
end
end
- local ok=false
+ local done=false
if lookaheaddisc then
local cf=start
local cl=getprev(lookaheaddisc)
@@ -19982,10 +20149,7 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
break
end
end
- setprev(lookaheaddisc,cprev)
- if cprev then
- setnext(cprev,lookaheaddisc)
- end
+ setlink(cprev,lookaheaddisc)
setprev(cf)
setnext(cl)
if startishead then
@@ -19994,25 +20158,35 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
local pre,post,replace=getdisc(lookaheaddisc)
local new=copy_node_list(cf)
local cnew=new
+ if pre then
+ setlink(find_node_tail(cf),pre)
+ end
+ if replace then
+ local tail=find_node_tail(new)
+ setlink(tail,replace)
+ end
for i=1,insertedmarks do
cnew=getnext(cnew)
end
+ cl=start
local clast=cnew
for i=f,l do
+ cl=getnext(cl)
clast=getnext(clast)
end
if not notmatchpre[lookaheaddisc] then
- cf,start,ok=chainproc(cf,start,last,dataset,sequence,chainlookup,rlmode,k)
+ local ok=false
+ cf,start,ok=chainrun(cf,start,cl,dataset,sequence,rlmode,ck,skipped)
+ if ok then
+ done=true
+ end
end
if not notmatchreplace[lookaheaddisc] then
- new,cnew,ok=chainproc(new,cnew,clast,dataset,sequence,chainlookup,rlmode,k)
- end
- if pre then
- setlink(cl,pre)
- end
- if replace then
- local tail=find_node_tail(new)
- setlink(tail,replace)
+ local ok=false
+ new,cnew,ok=chainrun(new,cnew,clast,dataset,sequence,rlmode,ck,skipped)
+ if ok then
+ done=true
+ end
end
if hasglue then
setdiscchecked(lookaheaddisc,cf,post,new)
@@ -20021,7 +20195,7 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
end
start=getprev(lookaheaddisc)
sweephead[cf]=getnext(clast)
- sweephead[new]=getnext(last)
+ sweephead[new]=getnext(cl)
elseif backtrackdisc then
local cf=getnext(backtrackdisc)
local cl=start
@@ -20054,10 +20228,18 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
clast=getnext(clast)
end
if not notmatchpost[backtrackdisc] then
- cf,start,ok=chainproc(cf,start,last,dataset,sequence,chainlookup,rlmode,k)
+ local ok=false
+ cf,start,ok=chainrun(cf,start,last,dataset,sequence,rlmode,ck,skipped)
+ if ok then
+ done=true
+ end
end
if not notmatchreplace[backtrackdisc] then
- new,cnew,ok=chainproc(new,cnew,clast,dataset,sequence,chainlookup,rlmode,k)
+ local ok=false
+ new,cnew,ok=chainrun(new,cnew,clast,dataset,sequence,rlmode,ck,skipped)
+ if ok then
+ done=true
+ end
end
if post then
setlink(posttail,cf)
@@ -20078,17 +20260,30 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
sweephead[post]=getnext(clast)
sweephead[replace]=getnext(last)
else
- head,start,ok=chainproc(head,start,last,dataset,sequence,chainlookup,rlmode,k)
+ local ok=false
+ head,start,ok=chainrun(head,start,last,dataset,sequence,rlmode,ck,skipped)
+ if ok then
+ done=true
+ end
end
- return head,start,ok
+ return head,start,done
+end
+local function chaintrac(head,start,dataset,sequence,rlmode,ck,skipped)
+ local rule=ck[1]
+ local lookuptype=ck[8] or ck[2]
+ local nofseq=#ck[3]
+ local first=ck[4]
+ local last=ck[5]
+ local char=getchar(start)
+ logwarning("%s: rule %s matches at char %s for (%s,%s,%s) chars, lookuptype %a",
+ cref(dataset,sequence),rule,gref(char),first-1,last-first+1,nofseq-last,lookuptype)
end
-local noflags={ false,false,false,false }
local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
local sweepnode=sweepnode
local sweeptype=sweeptype
local currentfont=currentfont
local diskseen=false
- local checkdisc=getprev(head)
+ local checkdisc=sweeptype and getprev(head)
local flags=sequence.flags or noflags
local done=false
local skipmark=flags[1]
@@ -20096,6 +20291,8 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
local skipbase=flags[3]
local markclass=sequence.markclass
local skipped=false
+ local startprev,
+ startnext=getboth(start)
for k=1,#contexts do
local match=true
local current=start
@@ -20107,7 +20304,9 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
if s==1 then
local char=ischar(current,currentfont)
if char then
- match=seq[1][char]
+ if not seq[1][char] then
+ match=false
+ end
end
else
local f=ck[4]
@@ -20116,7 +20315,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
if size>1 then
local discfound=nil
local n=f+1
- last=getnext(last)
+ last=startnext
while n<=l do
if not last and (sweeptype=="post" or sweeptype=="replace") then
last=getnext(sweepnode)
@@ -20125,9 +20324,8 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
if last then
local char,id=ischar(last,currentfont)
if char then
- local ccd=descriptions[char]
- if ccd then
- local class=ccd.class or "base"
+ local class=classes[char]
+ if class then
if class==skipmark or class==skipligature or class==skipbase or (markclass and class=="mark" and not markclass[char]) then
skipped=true
if trace_skips then
@@ -20142,7 +20340,9 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
else
if discfound then
notmatchreplace[discfound]=true
- match=not notmatchpre[discfound]
+ if notmatchpre[discfound] then
+ match=false
+ end
else
match=false
end
@@ -20151,7 +20351,9 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
else
if discfound then
notmatchreplace[discfound]=true
- match=not notmatchpre[discfound]
+ if notmatchpre[discfound] then
+ match=false
+ end
else
match=false
end
@@ -20160,7 +20362,9 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
elseif char==false then
if discfound then
notmatchreplace[discfound]=true
- match=not notmatchpre[discfound]
+ if notmatchpre[discfound] then
+ match=false
+ end
else
match=false
end
@@ -20202,11 +20406,15 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
end
else
notmatchreplace[last]=true
- match=not notmatchpre[last]
+ if notmatchpre[last] then
+ match=false
+ end
break
end
end
- match=not notmatchpre[last]
+ if notmatchpre[last] then
+ match=false
+ end
end
last=getnext(last)
else
@@ -20220,8 +20428,8 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
end
end
if match and f>1 then
- local prev=getprev(start)
- if prev then
+ if startprev then
+ local prev=startprev
if prev==checkdisc and (sweeptype=="pre" or sweeptype=="replace") then
prev=getprev(sweepnode)
end
@@ -20232,24 +20440,25 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
if prev then
local char,id=ischar(prev,currentfont)
if char then
- local ccd=descriptions[char]
- if ccd then
- local class=ccd.class
+ local class=classes[char]
+ if class then
if class==skipmark or class==skipligature or class==skipbase or (markclass and class=="mark" and not markclass[char]) then
skipped=true
if trace_skips then
show_skip(dataset,sequence,char,ck,class)
end
- prev=getprev(prev)
+ prev=getprev(prev)
elseif seq[n][char] then
- if n>1 then
- prev=getprev(prev)
+ if n>1 then
+ prev=getprev(prev)
end
n=n-1
else
if discfound then
notmatchreplace[discfound]=true
- match=not notmatchpost[discfound]
+ if notmatchpost[discfound] then
+ match=false
+ end
else
match=false
end
@@ -20258,7 +20467,9 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
else
if discfound then
notmatchreplace[discfound]=true
- match=not notmatchpost[discfound]
+ if notmatchpost[discfound] then
+ match=false
+ end
else
match=false
end
@@ -20267,7 +20478,9 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
elseif char==false then
if discfound then
notmatchreplace[discfound]=true
- match=not notmatchpost[discfound]
+ if notmatchpost[discfound] then
+ match=false
+ end
else
match=false
end
@@ -20318,7 +20531,9 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
end
else
notmatchreplace[prev]=true
- match=not notmatchpost[prev]
+ if notmatchpost[prev] then
+ match=false
+ end
break
end
end
@@ -20328,7 +20543,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
end
end
prev=getprev(prev)
- elseif seq[n][32] and isspace(prev,threshold) then
+ elseif seq[n][32] and id==glue_code and isspace(prev,threshold,id) then
n=n-1
prev=getprev(prev)
else
@@ -20361,9 +20576,8 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
if current then
local char,id=ischar(current,currentfont)
if char then
- local ccd=descriptions[char]
- if ccd then
- local class=ccd.class
+ local class=classes[char]
+ if class then
if class==skipmark or class==skipligature or class==skipbase or (markclass and class=="mark" and not markclass[char]) then
skipped=true
if trace_skips then
@@ -20378,7 +20592,9 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
else
if discfound then
notmatchreplace[discfound]=true
- match=not notmatchpre[discfound]
+ if notmatchpre[discfound] then
+ match=false
+ end
else
match=false
end
@@ -20387,7 +20603,9 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
else
if discfound then
notmatchreplace[discfound]=true
- match=not notmatchpre[discfound]
+ if notmatchpre[discfound] then
+ match=false
+ end
else
match=false
end
@@ -20396,7 +20614,9 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
elseif char==false then
if discfound then
notmatchreplace[discfound]=true
- match=not notmatchpre[discfound]
+ if notmatchpre[discfound] then
+ match=false
+ end
else
match=false
end
@@ -20438,7 +20658,9 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
end
else
notmatchreplace[current]=true
- match=notmatchpre[current]
+ if not notmatchpre[current] then
+ match=false
+ end
break
end
end
@@ -20448,7 +20670,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
else
end
current=getnext(current)
- elseif seq[n][32] and isspace(current,threshold) then
+ elseif seq[n][32] and id==glue_code and isspace(current,threshold,id) then
n=n+1
current=getnext(current)
else
@@ -20466,94 +20688,13 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
end
end
if match then
- local diskchain=diskseen or sweepnode
if trace_contexts then
- local rule=ck[1]
- local lookuptype=ck[8] or ck[2]
- local first=ck[4]
- local last=ck[5]
- local char=getchar(start)
- logwarning("%s: rule %s matches at char %s for (%s,%s,%s) chars, lookuptype %a",
- cref(dataset,sequence),rule,gref(char),first-1,last-first+1,s-last,lookuptype)
- end
- local chainlookups=ck[6]
- if chainlookups then
- local nofchainlookups=#chainlookups
- if size==1 then
- local chainlookup=chainlookups[1]
- local chainkind=chainlookup.type
- local chainproc=chainprocs[chainkind]
- if chainproc then
- local ok
- if diskchain then
- head,start,ok=chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,1,ck,chainproc)
- else
- head,start,ok=chainproc(head,start,last,dataset,sequence,chainlookup,rlmode,1)
- end
- if ok then
- done=true
- end
- else
- logprocess("%s: %s is not yet supported (1)",cref(dataset,sequence),chainkind)
- end
- else
- local i=1
- while start do
- if skipped then
- while start do
- local char=getchar(start)
- local ccd=descriptions[char]
- if ccd then
- local class=ccd.class or "base"
- if class==skipmark or class==skipligature or class==skipbase or (markclass and class=="mark" and not markclass[char]) then
- start=getnext(start)
- else
- break
- end
- else
- break
- end
- end
- end
- local chainlookup=chainlookups[i]
- if chainlookup then
- local chainkind=chainlookup.type
- local chainproc=chainprocs[chainkind]
- if chainproc then
- local ok,n
- if diskchain then
- head,start,ok=chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,i,ck,chainproc)
- else
- head,start,ok,n=chainproc(head,start,last,dataset,sequence,chainlookup,rlmode,i)
- end
- if ok then
- done=true
- if n and n>1 and i+n>nofchainlookups then
- break
- end
- end
- else
- logprocess("%s: %s is not yet supported (2)",cref(dataset,sequence),chainkind)
- end
- end
- i=i+1
- if i>size or not start then
- break
- elseif start then
- start=getnext(start)
- end
- end
- end
+ chaintrac(head,start,dataset,sequence,rlmode,ck,skipped)
+ end
+ if diskseen or sweepnode then
+ head,start,done=chaindisk(head,start,dataset,sequence,rlmode,ck,skipped)
else
- local replacements=ck[7]
- if replacements then
- head,start,done=reversesub(head,start,last,dataset,sequence,replacements,rlmode)
- else
- done=true
- if trace_contexts then
- logprocess("%s: skipping match",cref(dataset,sequence))
- end
- end
+ head,start,done=chainrun(head,start,last,dataset,sequence,rlmode,ck,skipped)
end
if done then
break
@@ -20610,75 +20751,79 @@ local sequencelists=setmetatableindex(function(t,font)
t[font]=sequences
return sequences
end)
-local autofeatures=fonts.analyzers.features
-local featuretypes=otf.tables.featuretypes
-local defaultscript=otf.features.checkeddefaultscript
-local defaultlanguage=otf.features.checkeddefaultlanguage
-local function initialize(sequence,script,language,enabled,autoscript,autolanguage)
- local features=sequence.features
- if features then
- local order=sequence.order
- if order then
- local featuretype=featuretypes[sequence.type or "unknown"]
- for i=1,#order do
- local kind=order[i]
- local valid=enabled[kind]
- if valid then
- local scripts=features[kind]
- local languages=scripts and (
- scripts[script] or
- scripts[wildcard] or
- (autoscript and defaultscript(featuretype,autoscript,scripts))
- )
- local enabled=languages and (
- languages[language] or
- languages[wildcard] or
- (autolanguage and defaultlanguage(featuretype,autolanguage,languages))
- )
- if enabled then
- return { valid,autofeatures[kind] or false,sequence,kind }
+do
+ local autofeatures=fonts.analyzers.features
+ local featuretypes=otf.tables.featuretypes
+ local defaultscript=otf.features.checkeddefaultscript
+ local defaultlanguage=otf.features.checkeddefaultlanguage
+ local wildcard="*"
+ local default="dflt"
+ local function initialize(sequence,script,language,enabled,autoscript,autolanguage)
+ local features=sequence.features
+ if features then
+ local order=sequence.order
+ if order then
+ local featuretype=featuretypes[sequence.type or "unknown"]
+ for i=1,#order do
+ local kind=order[i]
+ local valid=enabled[kind]
+ if valid then
+ local scripts=features[kind]
+ local languages=scripts and (
+ scripts[script] or
+ scripts[wildcard] or
+ (autoscript and defaultscript(featuretype,autoscript,scripts))
+ )
+ local enabled=languages and (
+ languages[language] or
+ languages[wildcard] or
+ (autolanguage and defaultlanguage(featuretype,autolanguage,languages))
+ )
+ if enabled then
+ return { valid,autofeatures[kind] or false,sequence,kind }
+ end
end
end
+ else
end
- else
end
+ return false
end
- return false
-end
-function otf.dataset(tfmdata,font)
- local shared=tfmdata.shared
- local properties=tfmdata.properties
- local language=properties.language or "dflt"
- local script=properties.script or "dflt"
- local enabled=shared.features
- local autoscript=enabled and enabled.autoscript
- local autolanguage=enabled and enabled.autolanguage
- local res=resolved[font]
- if not res then
- res={}
- resolved[font]=res
- end
- local rs=res[script]
- if not rs then
- rs={}
- res[script]=rs
- end
- local rl=rs[language]
- if not rl then
- rl={
- }
- rs[language]=rl
- local sequences=tfmdata.resources.sequences
- if sequences then
- for s=1,#sequences do
- local v=enabled and initialize(sequences[s],script,language,enabled,autoscript,autolanguage)
- if v then
- rl[#rl+1]=v
+ function otf.dataset(tfmdata,font)
+ local shared=tfmdata.shared
+ local properties=tfmdata.properties
+ local language=properties.language or "dflt"
+ local script=properties.script or "dflt"
+ local enabled=shared.features
+ local autoscript=enabled and enabled.autoscript
+ local autolanguage=enabled and enabled.autolanguage
+ local res=resolved[font]
+ if not res then
+ res={}
+ resolved[font]=res
+ end
+ local rs=res[script]
+ if not rs then
+ rs={}
+ res[script]=rs
+ end
+ local rl=rs[language]
+ if not rl then
+ rl={
+ }
+ rs[language]=rl
+ local sequences=tfmdata.resources.sequences
+ if sequences then
+ for s=1,#sequences do
+ local v=enabled and initialize(sequences[s],script,language,enabled,autoscript,autolanguage)
+ if v then
+ rl[#rl+1]=v
+ end
end
end
end
+ return rl
end
- return rl
end
local function report_disc(what,n)
report_run("%s: %s > %s",what,n,languages.serializediscretionary(n))
@@ -20759,12 +20904,11 @@ local function kernrun(disc,k_run,font,attr,...)
if k_run(prevmarks,"emptyinjections",next,font,attr,...) then
done=true
end
- setlink(prev,disc)
- setlink(disc,next)
+ setlink(prev,disc,next)
end
return nextstart,done
end
-local function comprun(disc,c_run,...)
+local function comprun(disc,c_run,...)
if trace_compruns then
report_disc("comp",disc)
end
@@ -20878,7 +21022,10 @@ local function c_run_single(head,font,attr,lookupcache,step,dataset,sequence,rlm
while start do
local char=ischar(start,font)
if char then
- local a=attr and getattr(start,0)
+ local a
+ if attr then
+ a=getattr(start,0)
+ end
if not a or (a==attr) then
local lookupmatch=lookupcache[char]
if lookupmatch then
@@ -20908,11 +21055,15 @@ local function t_run_single(start,stop,font,attr,lookupcache)
while start~=stop do
local char=ischar(start,font)
if char then
- local a=attr and getattr(start,0)
+ local a
+ if attr then
+ a=getattr(start,0)
+ end
+ local startnext=getnext(start)
if not a or (a==attr) then
local lookupmatch=lookupcache[char]
if lookupmatch then
- local s=getnext(start)
+ local s=startnext
local l=nil
local d=0
while s do
@@ -20935,14 +21086,17 @@ local function t_run_single(start,stop,font,attr,lookupcache)
end
else
end
- start=getnext(start)
+ start=starttnext
else
break
end
end
end
local function k_run_single(sub,injection,last,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
- local a=attr and getattr(sub,0)
+ local a
+ if attr then
+ a=getattr(sub,0)
+ end
if not a or (a==attr) then
for n in traverse_nodes(sub) do
if n==last then
@@ -20973,7 +21127,10 @@ local function c_run_multiple(head,font,attr,steps,nofsteps,dataset,sequence,rlm
while start do
local char=ischar(start,font)
if char then
- local a=attr and getattr(start,0)
+ local a
+ if attr then
+ a=getattr(start,0)
+ end
if not a or (a==attr) then
for i=1,nofsteps do
local step=steps[i]
@@ -21014,7 +21171,11 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps)
while start~=stop do
local char=ischar(start,font)
if char then
- local a=attr and getattr(start,0)
+ local a
+ if attr then
+ a=getattr(start,0)
+ end
+ local startnext=getnext(start)
if not a or (a==attr) then
for i=1,nofsteps do
local step=steps[i]
@@ -21022,7 +21183,7 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps)
if lookupcache then
local lookupmatch=lookupcache[char]
if lookupmatch then
- local s=getnext(start)
+ local s=startnext
local l=nil
local d=0
while s do
@@ -21049,14 +21210,17 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps)
end
else
end
- start=getnext(start)
+ start=startnext
else
break
end
end
end
local function k_run_multiple(sub,injection,last,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
- local a=attr and getattr(sub,0)
+ local a
+ if attr then
+ a=getattr(sub,0)
+ end
if not a or (a==attr) then
for n in traverse_nodes(sub) do
if n==last then
@@ -21084,7 +21248,7 @@ local function k_run_multiple(sub,injection,last,font,attr,steps,nofsteps,datase
end
end
local function txtdirstate(start,stack,top,rlparmode)
- local dir=getfield(start,"dir")
+ local dir=getdir(start)
local new=1
if dir=="+TRT" then
top=top+1
@@ -21107,7 +21271,7 @@ local function txtdirstate(start,stack,top,rlparmode)
return getnext(start),top,new
end
local function pardirstate(start)
- local dir=getfield(start,"dir")
+ local dir=getdir(start)
local new=0
if dir=="TLT" then
new=1
@@ -21131,9 +21295,11 @@ local function featuresprocessor(head,font,attr)
if nesting==1 then
currentfont=font
tfmdata=fontdata[font]
- descriptions=tfmdata.descriptions
- characters=tfmdata.characters
- marks=tfmdata.resources.marks
+ descriptions=tfmdata.descriptions
+ characters=tfmdata.characters
+ local resources=tfmdata.resources
+ marks=resources.marks
+ classes=resources.classes
threshold,
factor=getthreshold(font)
checkmarks=tfmdata.properties.checkmarks
@@ -21149,7 +21315,6 @@ local function featuresprocessor(head,font,attr)
local rlmode=0
local done=false
local datasets=otf.dataset(tfmdata,font,attr)
- local forcedisc=alwaysdisc or not attr
local dirstack={}
sweephead={}
for s=1,#datasets do
@@ -21158,7 +21323,6 @@ local function featuresprocessor(head,font,attr)
local sequence=dataset[3]
local rlparmode=0
local topstack=0
- local success=false
local typ=sequence.type
local gpossing=typ=="gpos_single" or typ=="gpos_pair"
local handler=handlers[typ]
@@ -21167,7 +21331,7 @@ local function featuresprocessor(head,font,attr)
if not steps then
local h,d,ok=handler(head,head,dataset,sequence,nil,nil,nil,0,font,attr)
if ok then
- success=true
+ done=true
if h then
head=h
end
@@ -21177,7 +21341,10 @@ local function featuresprocessor(head,font,attr)
while start do
local char=ischar(start,font)
if char then
- local a=attr and getattr(start,0)
+ local a
+ if attr then
+ a=getattr(start,0)
+ end
if not a or (a==attr) then
for i=1,nofsteps do
local step=steps[i]
@@ -21188,7 +21355,7 @@ local function featuresprocessor(head,font,attr)
local ok
head,start,ok=handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i)
if ok then
- success=true
+ done=true
break
end
end
@@ -21218,11 +21385,13 @@ local function featuresprocessor(head,font,attr)
while start do
local char,id=ischar(start,font)
if char then
- local a=attr and getattr(start,0)
- if a then
- a=(a==attr) and (not attribute or getprop(start,a_state)==attribute)
- else
- a=not attribute or getprop(start,a_state)==attribute
+ local a
+ if attr then
+ if getattr(start,0)==attr and (not attribute or getprop(start,a_state)==attribute) then
+ a=true
+ end
+ elseif not attribute or getprop(start,a_state)==attribute then
+ a=true
end
if a then
local lookupmatch=lookupcache[char]
@@ -21230,7 +21399,7 @@ local function featuresprocessor(head,font,attr)
local ok
head,start,ok=handler(head,start,dataset,sequence,lookupmatch,rlmode,step,1)
if ok then
- success=true
+ done=true
end
end
if start then
@@ -21242,21 +21411,16 @@ local function featuresprocessor(head,font,attr)
elseif char==false then
start=getnext(start)
elseif id==disc_code then
- local a=forcedisc or getsubtype(start)==discretionary_code or getattr(start,0)==attr
- if a then
- local ok
- if gpossing then
- start,ok=kernrun(start,k_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
- elseif typ=="gsub_ligature" then
- start,ok=testrun(start,t_run_single,c_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
- else
- start,ok=comprun(start,c_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
- end
- if ok then
- success=true
- end
+ local ok
+ if gpossing then
+ start,ok=kernrun(start,k_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
+ elseif typ=="gsub_ligature" then
+ start,ok=testrun(start,t_run_single,c_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
else
- start=getnext(start)
+ start,ok=comprun(start,c_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
+ end
+ if ok then
+ done=true
end
elseif id==math_code then
start=getnext(end_of_math(start))
@@ -21273,11 +21437,13 @@ local function featuresprocessor(head,font,attr)
while start do
local char,id=ischar(start,font)
if char then
- local a=attr and getattr(start,0)
- if a then
- a=(a==attr) and (not attribute or getprop(start,a_state)==attribute)
- else
- a=not attribute or getprop(start,a_state)==attribute
+ local a
+ if attr then
+ if getattr(start,0)==attr and (not attribute or getprop(start,a_state)==attribute) then
+ a=true
+ end
+ elseif not attribute or getprop(start,a_state)==attribute then
+ a=true
end
if a then
for i=1,nofsteps do
@@ -21289,7 +21455,7 @@ local function featuresprocessor(head,font,attr)
local ok
head,start,ok=handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i)
if ok then
- success=true
+ done=true
break
elseif not start then
break
@@ -21308,21 +21474,16 @@ local function featuresprocessor(head,font,attr)
elseif char==false then
start=getnext(start)
elseif id==disc_code then
- local a=forcedisc or getsubtype(start)==discretionary_code or getattr(start,0)==attr
- if a then
- local ok
- if gpossing then
- start,ok=kernrun(start,k_run_multiple,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
- elseif typ=="gsub_ligature" then
- start,ok=testrun(start,t_run_multiple,c_run_multiple,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
- else
- start,ok=comprun(start,c_run_multiple,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
- end
- if ok then
- success=true
- end
+ local ok
+ if gpossing then
+ start,ok=kernrun(start,k_run_multiple,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
+ elseif typ=="gsub_ligature" then
+ start,ok=testrun(start,t_run_multiple,c_run_multiple,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
else
- start=getnext(start)
+ start,ok=comprun(start,c_run_multiple,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
+ end
+ if ok then
+ done=true
end
elseif id==math_code then
start=getnext(end_of_math(start))
@@ -21336,9 +21497,6 @@ local function featuresprocessor(head,font,attr)
end
end
end
- if success then
- done=true
- end
if trace_steps then
registerstep(head)
end
@@ -22472,8 +22630,7 @@ function handlers.devanagari_reorder_reph(head,start)
if getprop(current,a_state)==s_pstf then
startnext=getnext(start)
head=remove_node(head,start)
- local prev=getprev(current)
- setlink(prev,start)
+ setlink(getprev(current),start)
setlink(start,current)
start=startnext
startattr=getprop(start,a_syllabe)
@@ -22502,8 +22659,7 @@ function handlers.devanagari_reorder_reph(head,start)
if c then
startnext=getnext(start)
head=remove_node(head,start)
- local prev=getprev(c)
- setlink(prev,start)
+ setlink(getprev(c),start)
setlink(start,c)
start=startnext
startattr=getprop(start,a_syllabe)
@@ -22524,8 +22680,7 @@ function handlers.devanagari_reorder_reph(head,start)
if start~=current then
startnext=getnext(start)
head=remove_node(head,start)
- local next=getnext(current)
- setlink(start,next)
+ setlink(start,getnext(current))
setlink(current,start)
start=startnext
end
@@ -22573,8 +22728,7 @@ function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start)
if not consonant[char] and getprop(current,a_state) then
startnext=getnext(start)
removenode(start,start)
- local prev=getprev(current)
- setlink(prev,start)
+ setlink(getprev(current),start)
setlink(start,current)
start=startnext
break
@@ -22867,8 +23021,7 @@ local function dev2_reorder(head,start,stop,font,attr,nbspaces)
end
start=current
end
- local prev=getprev(halfpos)
- setlink(prev,current)
+ setlink(getprev(halfpos),current)
setlink(current,halfpos)
halfpos=current
elseif above_mark[char] then
@@ -22898,8 +23051,7 @@ local function dev2_reorder(head,start,stop,font,attr,nbspaces)
if current==stop then
stop=prev
end
- local next=getnext(target)
- setlink(current,next)
+ setlink(current,getnext(target))
setlink(target,current)
end
end
@@ -22924,8 +23076,7 @@ local function dev2_reorder(head,start,stop,font,attr,nbspaces)
if stop==next then
stop=current
end
- local prev=getprev(c)
- setlink(prev,next)
+ setlink(getprev(c),next)
local nextnext=getnext(next)
setnext(current,nextnext)
local nextnextnext=getnext(nextnext)
@@ -23730,42 +23881,61 @@ do
return entry.data
end
end
+ local runner=sandbox and sandbox.registerrunner {
+ name="otfsvg",
+ program="inkscape",
+ method="pipeto",
+ template="--shell > temp-otf-svg-shape.log",
+ reporter=report_svg,
+ }
+ if notrunner then
+ runner=function()
+ return io.open("inkscape --shell > temp-otf-svg-shape.log","w")
+ end
+ end
function otfsvg.topdf(svgshapes)
- local inkscape=io.popen("inkscape --shell > temp-otf-svg-shape.log","w")
local pdfshapes={}
- local nofshapes=#svgshapes
- local f_svgfile=formatters["temp-otf-svg-shape-%i.svg"]
- local f_pdffile=formatters["temp-otf-svg-shape-%i.pdf"]
- local f_convert=formatters["%s --export-pdf=%s\n"]
- local filterglyph=otfsvg.filterglyph
- report_svg("processing %i svg containers",nofshapes)
- statistics.starttiming()
- for i=1,nofshapes do
- local entry=svgshapes[i]
- for index=entry.first,entry.last do
- local data=filterglyph(entry,index)
- if data and data~="" then
- local svgfile=f_svgfile(index)
- local pdffile=f_pdffile(index)
- savedata(svgfile,data)
- inkscape:write(f_convert(svgfile,pdffile))
- pdfshapes[index]=true
- end
- end
- end
- inkscape:write("quit\n")
- inkscape:close()
- report_svg("processing %i pdf results",nofshapes)
- for index in next,pdfshapes do
- local svgfile=f_svgfile(index)
- local pdffile=f_pdffile(index)
- pdfshapes[index]=loaddata(pdffile)
- remove(svgfile)
- remove(pdffile)
- end
- statistics.stoptiming()
- if statistics.elapsedseconds then
- report_svg("svg conversion time %s",statistics.elapsedseconds())
+ local inkscape=runner()
+ if inkscape then
+ local nofshapes=#svgshapes
+ local f_svgfile=formatters["temp-otf-svg-shape-%i.svg"]
+ local f_pdffile=formatters["temp-otf-svg-shape-%i.pdf"]
+ local f_convert=formatters["%s --export-pdf=%s\n"]
+ local filterglyph=otfsvg.filterglyph
+ local nofdone=0
+ report_svg("processing %i svg containers",nofshapes)
+ statistics.starttiming()
+ for i=1,nofshapes do
+ local entry=svgshapes[i]
+ for index=entry.first,entry.last do
+ local data=filterglyph(entry,index)
+ if data and data~="" then
+ local svgfile=f_svgfile(index)
+ local pdffile=f_pdffile(index)
+ savedata(svgfile,data)
+ inkscape:write(f_convert(svgfile,pdffile))
+ pdfshapes[index]=true
+ nofdone=nofdone+1
+ if nofdone%100==0 then
+ report_svg("%i shapes processed",nofdone)
+ end
+ end
+ end
+ end
+ inkscape:write("quit\n")
+ inkscape:close()
+ report_svg("processing %i pdf results",nofshapes)
+ for index in next,pdfshapes do
+ local svgfile=f_svgfile(index)
+ local pdffile=f_pdffile(index)
+ pdfshapes[index]=loaddata(pdffile)
+ remove(svgfile)
+ remove(pdffile)
+ end
+ statistics.stoptiming()
+ if statistics.elapsedseconds then
+ report_svg("svg conversion time %s",statistics.elapsedseconds())
+ end
end
return pdfshapes
end