summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorHans Hagen <pragma@wxs.nl>2022-07-06 22:05:18 +0200
committerContext Git Mirror Bot <phg@phi-gamma.net>2022-07-06 22:05:18 +0200
commit82c674fdcf5bcff4ad0dc0936d638fc729145616 (patch)
tree6ab4ee4417aa22180cd5b3c50ede6a031f8ce3f9 /doc
parent3a55e11c7295abf8f2dfe5e9d1c8b153f4518824 (diff)
downloadcontext-82c674fdcf5bcff4ad0dc0936d638fc729145616.tar.gz
2022-07-06 21:35:00
Diffstat (limited to 'doc')
-rw-r--r--doc/context/documents/general/manuals/columnsets.pdfbin4509576 -> 2404352 bytes
-rw-r--r--doc/context/documents/general/manuals/ontarget.pdfbin319134 -> 539819 bytes
-rw-r--r--doc/context/scripts/mkiv/mtx-vscode.html1
-rw-r--r--doc/context/scripts/mkiv/mtx-vscode.man3
-rw-r--r--doc/context/scripts/mkiv/mtx-vscode.xml1
-rw-r--r--doc/context/sources/general/manuals/columnsets/columnsets-004.tex2
-rw-r--r--doc/context/sources/general/manuals/columnsets/columnsets-204.tex2
-rw-r--r--doc/context/sources/general/manuals/columnsets/columnsets-205.tex2
-rw-r--r--doc/context/sources/general/manuals/columnsets/columnsets-702.tex1
-rw-r--r--doc/context/sources/general/manuals/luametatex/luametatex-differences.tex20
-rw-r--r--doc/context/sources/general/manuals/luametatex/luametatex-introduction.tex33
-rw-r--r--doc/context/sources/general/manuals/manuals-xml-environment.tex3
-rw-r--r--doc/context/sources/general/manuals/ontarget/ontarget-alsomath.tex90
-rw-r--r--doc/context/sources/general/manuals/ontarget/ontarget-binary.tex99
-rw-r--r--doc/context/sources/general/manuals/ontarget/ontarget-dk.tex2
-rw-r--r--doc/context/sources/general/manuals/ontarget/ontarget-makesnosense.tex213
-rw-r--r--doc/context/sources/general/manuals/ontarget/ontarget-makessense.tex110
-rw-r--r--doc/context/sources/general/manuals/ontarget/ontarget-math.tex285
-rw-r--r--doc/context/sources/general/manuals/ontarget/ontarget-metapost.tex755
-rw-r--r--doc/context/sources/general/manuals/ontarget/ontarget-ridofjit.tex111
-rw-r--r--doc/context/sources/general/manuals/ontarget/ontarget.tex6
21 files changed, 1717 insertions, 22 deletions
diff --git a/doc/context/documents/general/manuals/columnsets.pdf b/doc/context/documents/general/manuals/columnsets.pdf
index 3a031fe7c..b426cf98d 100644
--- a/doc/context/documents/general/manuals/columnsets.pdf
+++ b/doc/context/documents/general/manuals/columnsets.pdf
Binary files differ
diff --git a/doc/context/documents/general/manuals/ontarget.pdf b/doc/context/documents/general/manuals/ontarget.pdf
index e4fb54bc4..c8c3fe854 100644
--- a/doc/context/documents/general/manuals/ontarget.pdf
+++ b/doc/context/documents/general/manuals/ontarget.pdf
Binary files differ
diff --git a/doc/context/scripts/mkiv/mtx-vscode.html b/doc/context/scripts/mkiv/mtx-vscode.html
index f66227be7..7dccefd49 100644
--- a/doc/context/scripts/mkiv/mtx-vscode.html
+++ b/doc/context/scripts/mkiv/mtx-vscode.html
@@ -42,6 +42,7 @@
<tr><th>--generate</th><td></td><td>generate extension in sync with current version</td></tr>
<tr><th>--program</th><td></td><td>use the given binary (e.g. codium, default: code)</td></tr>
<tr><th>--start</th><td></td><td>start vscode with extension context</td></tr>
+ <tr><th>--lsfile</th><td></td><td>generate language server file (work in progress)</td></tr>
</table>
<br/>
<h1>Example</h1>
diff --git a/doc/context/scripts/mkiv/mtx-vscode.man b/doc/context/scripts/mkiv/mtx-vscode.man
index 563ca0518..e364ede50 100644
--- a/doc/context/scripts/mkiv/mtx-vscode.man
+++ b/doc/context/scripts/mkiv/mtx-vscode.man
@@ -19,6 +19,9 @@ use the given binary (e.g. codium, default: code)
.TP
.B --start
start vscode with extension context
+.TP
+.B --lsfile
+generate language server file (work in progress)
.SH AUTHOR
More information about ConTeXt and the tools that come with it can be found at:
diff --git a/doc/context/scripts/mkiv/mtx-vscode.xml b/doc/context/scripts/mkiv/mtx-vscode.xml
index 4af57773a..c9f1e62b1 100644
--- a/doc/context/scripts/mkiv/mtx-vscode.xml
+++ b/doc/context/scripts/mkiv/mtx-vscode.xml
@@ -11,6 +11,7 @@
<flag name="generate"><short>generate extension in sync with current version</short></flag>
<flag name="program"><short>use the given binary (e.g. codium, default: code)</short></flag>
<flag name="start"><short>start vscode with extension context</short></flag>
+ <flag name="lsfile"><short>generate language server file (work in progress)</short></flag>
</subcategory>
</category>
</flags>
diff --git a/doc/context/sources/general/manuals/columnsets/columnsets-004.tex b/doc/context/sources/general/manuals/columnsets/columnsets-004.tex
index cda3eb2fd..3cd217a3d 100644
--- a/doc/context/sources/general/manuals/columnsets/columnsets-004.tex
+++ b/doc/context/sources/general/manuals/columnsets/columnsets-004.tex
@@ -2,8 +2,6 @@
\definecolumnset[example][n=3,page=left]
-\definecolor[fakerulecolor]
-
\definecolumnsetspan[wide] [n=2,background=contrast,color=white]
\definecolumnsetspan[wider][n=4,background=contrast,color=white]
diff --git a/doc/context/sources/general/manuals/columnsets/columnsets-204.tex b/doc/context/sources/general/manuals/columnsets/columnsets-204.tex
index 480eb4ce5..5b0376f8f 100644
--- a/doc/context/sources/general/manuals/columnsets/columnsets-204.tex
+++ b/doc/context/sources/general/manuals/columnsets/columnsets-204.tex
@@ -1,4 +1,4 @@
-\usemodule[oldfun]
+\usemodule[oldfun] % really ?
\environment columnsets-000
diff --git a/doc/context/sources/general/manuals/columnsets/columnsets-205.tex b/doc/context/sources/general/manuals/columnsets/columnsets-205.tex
index 98305683e..7d77d5308 100644
--- a/doc/context/sources/general/manuals/columnsets/columnsets-205.tex
+++ b/doc/context/sources/general/manuals/columnsets/columnsets-205.tex
@@ -1,4 +1,4 @@
-\usemodule[oldfun]
+\usemodule[oldfun] % really ?
\environment columnsets-000
diff --git a/doc/context/sources/general/manuals/columnsets/columnsets-702.tex b/doc/context/sources/general/manuals/columnsets/columnsets-702.tex
index 770076623..7e0185ba1 100644
--- a/doc/context/sources/general/manuals/columnsets/columnsets-702.tex
+++ b/doc/context/sources/general/manuals/columnsets/columnsets-702.tex
@@ -1,4 +1,3 @@
-
\environment columnsets-000
\definecolumnset[example][n=4,page=left]
diff --git a/doc/context/sources/general/manuals/luametatex/luametatex-differences.tex b/doc/context/sources/general/manuals/luametatex/luametatex-differences.tex
index 3da557f40..8dcd2f2d1 100644
--- a/doc/context/sources/general/manuals/luametatex/luametatex-differences.tex
+++ b/doc/context/sources/general/manuals/luametatex/luametatex-differences.tex
@@ -279,6 +279,19 @@ end
if luatex and luametatex then
+ local match = string.match
+
+ local index = structures.registers.collected and structures.registers.collected.luatexindex
+ local found = { }
+
+ if index then
+ local data = index.entries
+ for i=1,#data do
+ found[match(data[i].list[1][1],"\\tex%s*{(.-)}") or ""] = true
+ end
+ -- inspect(found)
+ end
+
luatex = table.tohash(luatex)
luametatex = table.tohash(luametatex)
@@ -291,6 +304,9 @@ if luatex and luametatex then
context.startcolumns { n = 2 }
for k, v in table.sortedhash(luatex) do
if not luametatex[k] then
+ if not found[k] then
+ context.dontleavehmode()
+ end
context.type(k)
context.crlf()
end
@@ -307,6 +323,10 @@ if luatex and luametatex then
context.startcolumns { n = 2 }
for k, v in table.sortedhash(luametatex) do
if not luatex[k] then
+ if not found[k] then
+ context.dontleavehmode()
+ context.llap("\\infofont[todo] ")
+ end
context.type(k)
context.crlf()
end
diff --git a/doc/context/sources/general/manuals/luametatex/luametatex-introduction.tex b/doc/context/sources/general/manuals/luametatex/luametatex-introduction.tex
index 36336e42e..08b7d94bc 100644
--- a/doc/context/sources/general/manuals/luametatex/luametatex-introduction.tex
+++ b/doc/context/sources/general/manuals/luametatex/luametatex-introduction.tex
@@ -105,21 +105,36 @@ in, so if you want to complain about \LUAMETATEX, don't bother me. Of course, if
you really need professional support with these engines (or \TEX\ in general),
you can always consider contacting the developers.
+In 2021|--|2022 the math engine was fundamentally overhauled. As a side effect
+some additional features were added. Not all are yet described in the manual:
+some are still experimental and it just takes time and effort to document and the
+priorities are with implementing their usage. Given the long term stability of
+math and them unlikely to be used in other macro packages there is no real urge
+anyway. It is also easier when we have examples of usage. Of course much is
+discussed in \type {ontarget.pdf} and presentations. The same is true for
+additions to \METAPOST: in due time these will be discussed in the \LUAMETAFUN\
+manual (the official \METAPOST\ manual is maintained elsewhere and should not
+discuss features that are not in the \LUATEX\ version).
+
\blank[big]
Hans Hagen
\blank[2*big]
-\starttabulate[|||]
-\NC \LUAMETATEX\ Banner \EQ \cldcontext{LUATEXENGINE} %
- \cldcontext{LUATEXVERSION} / %
- \cldcontext{LUATEXFUNCTIONALITY}
- \NC \NR
-\NC \LUAMETATEX\ Version \EQ \currentdate \NC \NR
-\NC \CONTEXT\ Version \EQ LMTX \contextversion \NC \NR
-\NC \LUATEX\ Team \EQ Hans Hagen, Hartmut Henkel, Taco Hoekwater, Luigi Scarso \NC \NR
-\NC \LUAMETATEX\ Team \EQ Hans Hagen, Alan Braslau, Mojca Miklavec and Wolfgang Schuster \NC \NR
+\starttabulate[||pl|]
+\NC \LUAMETATEX\ Banner \EQ \cldcontext{LUATEXENGINE} %
+ \cldcontext{LUATEXVERSION} / %
+ \cldcontext{LUATEXFUNCTIONALITY}
+ \NC \NR
+\NC \LUAMETATEX\ Version \EQ \currentdate \NC \NR
+\NC \CONTEXT\ Version \EQ LMTX \contextversion \NC \NR
+\NC \LUATEX\ Team \EQ Hans Hagen, Hartmut Henkel, Taco Hoekwater, Luigi Scarso \NC \NR
+\NC \LUAMETATEX\ Team \EQ Hans Hagen, Alan Braslau, Mojca Miklavec and Wolfgang Schuster, Mikael Sundqvist \NC \NR
+\NC resources and info at \EQ www.contextgarden.net\space\vl\space
+ www.pragma-ade.nl\space\vl\space
+ www.luametatex.org\space\vl\space
+ ntg-context@ntg.nl (http://www.ntg.nl/mailman/listinfo/ntg-context) \NC \NR
\stoptabulate
\stopchapter
diff --git a/doc/context/sources/general/manuals/manuals-xml-environment.tex b/doc/context/sources/general/manuals/manuals-xml-environment.tex
index 5e66b6283..b5adb5b6a 100644
--- a/doc/context/sources/general/manuals/manuals-xml-environment.tex
+++ b/doc/context/sources/general/manuals/manuals-xml-environment.tex
@@ -1,7 +1,4 @@
% language=us
-%
-% author : Hans Hagen, PRAGMA ADE, NL
-% license : Creative Commons, Attribution-NonCommercial-ShareAlike 3.0 Unported
\usemodule[abr-01]
diff --git a/doc/context/sources/general/manuals/ontarget/ontarget-alsomath.tex b/doc/context/sources/general/manuals/ontarget/ontarget-alsomath.tex
new file mode 100644
index 000000000..19acc43d3
--- /dev/null
+++ b/doc/context/sources/general/manuals/ontarget/ontarget-alsomath.tex
@@ -0,0 +1,90 @@
+% language=us runpath=texruns:manuals/ontarget
+
+\startcomponent ontarget-alsomath
+
+\environment ontarget-style
+
+\startchapter[title={The curious case of \type {\over}}]
+
+Normally \TEX\ scans forward but there are a few special cases. First of all,
+\TEX\ is either scanning regular content or it is scanning alignments. That
+results in intercepts in all kind of places. When a row ends, scanning for
+inter|-|row actions happens. When the preamble is scanned there is some lookahead
+with partial expansion. This has side effects but these can be avoided in
+\LUAMETATEX\ by several options. Another special case is math mode. Normally
+curly braces indicate grouping but not in math mode: there they construct an
+atom, ordinary by default. Although most math constructs actually pick up some
+following atom, in which case we get a wrapped construct that actually is
+processed in a nested cal to the math processing routine. That whole has a class
+and although in \LUAMETATEX\ we can make atoms with a different left end right
+class, normally what is inside is hidden stays hidden. \footnote {We can think of
+optionally exposing the edge classes but although it is easy to implement we see
+no reason to do that now. After all, the information is actually available
+already via variables.}
+
+Fraction commands like \type {\over} and \type {\above} are used like this:
+
+\starttyping
+a + 1 \over 2 + b
+\stoptyping
+
+and as there can be more than for instance single digits we can do:
+
+\starttyping
+a + {12} \over {34} + b
+\stoptyping
+
+but it doesn't end there because you actually need to wrap:
+
+\starttyping
+a + {{12} \over {34}} + b
+\stoptyping
+
+If you don't do this $b$ will become part of the fraction. The curly braces here
+make the $12$, $34$ and the whole fraction made from them ordinary atoms. Because
+that also influences spacing one should be aware of side effects.
+
+\starttyping
+a + {{12} \over {34}} + b
+\stoptyping
+
+The argument of \type {simplicity} of input is easily defeated by using
+
+\starttyping
+a + \frac{12}{34} + b
+\stoptyping
+
+because it also reads sequential, is in sync with other commands like \type
+{\sqrt} and actually uses less tokens. It used more runtime, also because
+\CONTEXT\ adds plenty of control and extras but you won't notice it.
+
+Because in \CONTEXT\ we assume users to use \type {\frac} it made sense to see if
+we can make curly braces act like groups. In \LUAMETATEX\ we already have \type
+{\beginmathgroup} and \type {\endmathgroup} that provide grouping with mathstyle
+recovery, and by setting \type {\mathgroupingmode} to a non|-|zero value curly
+braces will act like these.
+
+The effects are subtle:
+
+\showmakeup[mathglue]
+
+\startbuffer
+$ a + { \bf x } ^ 2 + {\bf 1} + {\red 123} +
+\frac{1}{2} + {\scriptstyle 123} + \dd $
+\stopbuffer
+
+\typebuffer
+
+\startcombination[1*2]
+ {\scale[scale=2500]{\showmakeup[mathglue] \mathgroupingmode 0 \getbuffer}} {\type {\mathgroupingmode 0}}
+ {\scale[scale=2500]{\showmakeup[mathglue] \mathgroupingmode 1 \getbuffer}} {\type {\mathgroupingmode 1}}
+\stopcombination
+
+If you see the differences you might be happy with this new trick, if not, you
+probably are not that much into optimal math spacing anyway and you can forget
+about what you just read.
+
+\stopchapter
+
+\stopcomponent
+
diff --git a/doc/context/sources/general/manuals/ontarget/ontarget-binary.tex b/doc/context/sources/general/manuals/ontarget/ontarget-binary.tex
new file mode 100644
index 000000000..b3fbff7ec
--- /dev/null
+++ b/doc/context/sources/general/manuals/ontarget/ontarget-binary.tex
@@ -0,0 +1,99 @@
+% language=us runpath=texruns:manuals/ontarget
+
+\startcomponent ontarget-binary
+
+\environment ontarget-style
+
+\startchapter[title={The binary}]
+
+This is a very short chapter. Because \LUAMETATEX\ is also a script runner, I
+want to keep it lean and mean. So, when the size exceeded 3MB after we'd extended
+the math engine, I decided to (finally) let all the \METAPOST\ number interfaces
+pass pointers which brought down the binary 100K and below the 3MB mark again.
+
+I then became curious about how much of the binary actually is taken by
+\METAPOST, and a bit of calculation indicated that we went from 20.1\percent\ down
+to 18.3\percent. Here is the state per May 13, 2022:
+
+\startluacode
+
+ local bytes = {
+ liblua = 515156,
+ libluaoptional= 103668,
+ libluarest = 82492,
+ libluasocket = 105700,
+ libmimalloc = 178800,
+ libminiz = 51584,
+ libmp = 797636,
+ libmp = 797636, -- went from 20.1% to 18.3% after going more pointers
+ -- libmp = 797636 + (3061799 - 2960091),
+ libpplib = 325162,
+ libtex = 2207190,
+ }
+
+ local comment = {
+ liblua = "lua core, tex interfaces",
+ libluaoptional= "framework, several small interfaces, cerf",
+ libluarest = "general helper libraries",
+ libluasocket = "helper that interfaces to the os libraries",
+ libmimalloc = "memory management partial",
+ libminiz = "minimalistic core",
+ libmp = "mp graphic core, number libraries, lua interfacing",
+ libpplib = "pdf reading core, encryption helpers",
+ libtex = "extended tex core",
+ }
+
+ local luametatex = 2960091
+ local libraries = 0 for k, v in next, bytes do libraries = libraries + v end
+ local normalizer = luametatex/libraries
+
+ local luastuff = bytes.liblua
+ + bytes.libluaoptional
+ + bytes.libluarest
+ + bytes.libluasocket
+
+ -------(luametatex) context.par()
+ -------(libraries) context.par()
+ -------(normalizer) context.par()
+
+ context.starttabulate { "|l|r|r|p|" }
+ context.FL()
+ context.NC() context.bold("component")
+ context.NC() context.bold("pct")
+ context.NC() context.bold("bytes")
+ context.NC() context.bold("comment")
+ context.NC() context.NR()
+ context.ML()
+ for k, v in table.sortedpairs(bytes) do
+ context.NC() context(k)
+ context.NC() context("%.1f",100*v/libraries)
+ context.NC() context(math.round(normalizer*v))
+ context.NC() context(comment[k])
+ context.NC() context.NR()
+ end
+ context.ML()
+ context.NC() context.bold("luametatex")
+ context.NC()
+ context.NC() context.bold(luametatex)
+ context.NC() context("2022-05-13")
+ context.NC() context.NR()
+ context.LL()
+ context.stoptabulate()
+
+ function document.texstuff() context("%.1f\\percent",100 * bytes.libtex /libraries) end
+ function document.mpsstuff() context("%.1f\\percent",100 * bytes.libmp /libraries) end
+ function document.pdfstuff() context("%.1f\\percent",100 * bytes.libpplib/libraries) end
+ function document.luastuff() context("%.1f\\percent",100 * luastuff /libraries) end
+
+\stopluacode
+
+It is clear that the \TEX\ core is good for half of the code (\ctxlua {document .
+texstuff ()}) with the accumulated \LUA\ stuff (\ctxlua {document . luastuff ()})
+and \METAPOST\ being a good second (\ctxlua {document . mpsstuff ()}) and third
+and the \PDF\ interpreting library a decent fourth (\ctxlua {document . pdfstuff
+()}) place.
+
+\stopchapter
+
+\stopcomponent
+
diff --git a/doc/context/sources/general/manuals/ontarget/ontarget-dk.tex b/doc/context/sources/general/manuals/ontarget/ontarget-dk.tex
index 5d57da1b7..d1df3b8cc 100644
--- a/doc/context/sources/general/manuals/ontarget/ontarget-dk.tex
+++ b/doc/context/sources/general/manuals/ontarget/ontarget-dk.tex
@@ -57,7 +57,7 @@ When compared to the already present units the \type {dk} nicely fills a gap:
\TheUnit{cc}
\TheUnit{cm}
\TheUnit{in}
-
+
%\TheUnit{em}
%\TheUnit{ex}
%\TheUnit{mu}
diff --git a/doc/context/sources/general/manuals/ontarget/ontarget-makesnosense.tex b/doc/context/sources/general/manuals/ontarget/ontarget-makesnosense.tex
new file mode 100644
index 000000000..3a9e45e5e
--- /dev/null
+++ b/doc/context/sources/general/manuals/ontarget/ontarget-makesnosense.tex
@@ -0,0 +1,213 @@
+% language=us runpath=texruns:manuals/ontarget
+
+\startcomponent ontarget-makesnosense
+
+\environment ontarget-style
+
+\startchapter[title={Not all makes sense}]
+
+The development of \CONTEXT\ is to a large extend driven by users with a wide
+variety of background and usage. I can safely say that much time spent on
+\CONTEXT\ qualifies as hobby (or maybe even more by curiosity). Of course I do
+use it myself but personally I never make advanced documents. I'm not a writer,
+nor an artist, nor a typesetter. I do like challenges so that's why we get
+mechanisms that can do tricky things and some stay sort of hidden because the
+practical usage is limited, although you will be surprised to see what users find
+in the source and use anyway. My colleague uses \CONTEXT\ for large scale, mostly
+complex and demanding \XML\ documents where one source is rendered in different
+ways with different parts used. Many features in \CONTEXT\ relate to workflows.
+
+I like to visualize things so that's part of the development cycle. I never start
+from some \quote {typographical} point of view, if only because in my experience
+much design is arbitrary and personal. The output should look okay on the
+average, and on reasonable simple documents there should be no need for manual
+intervention. I am quite willing to accept an occasional less optimal looking
+page and don't loose sleep over it. A next time, when a sentence gets added, it
+might be better and the problem can be moved further down the pages. Also, given
+what one runs into nowadays the average job that \TEX\ does is pretty good (but
+users can of course mess up). It is boundary conditions that determine in what
+direction a style or solution goes. The more abstract one argues about
+typesetting and possible solutions, the less interested I often become simply
+because there are no perfect solutions for every case. There are always those
+last few \percent\ points that need manual intervention or some trickery and most
+users get that. It is also what makes using \TEX\ fun.
+
+As mentioned, the \TEX\ engine does a pretty good job on average but that didn't
+prevent me from extending it: the mix of \TEX, \METAPOST\ and \LUA\ is even more
+fun. But what is the development agenda there? Again, it is very much driven by
+what users want me to solve, but there's also the curiosity element. A recent
+example of extending is the math sub system. It was already made more
+configurable and some features where added but now it is really flexible. This
+was doable because the heuristics in the engine are clear. It was could be done
+because I had a dedicated partner in this journey. \footnote {In another chapter
+I summarize what Mikael Sundqvist and I did in this context.} Other parts are
+more difficult but have nevertheless been extended, to mention a few: alignments,
+par building and page building. However the last two use some heuristics that are
+hard to make more flexible. For instance the badness calculation combined with
+the loop that tries to find breakpoints is already quite good and the somewhat
+special values involved in the calculations have been optimized stepwise by Don
+Knuth during the development of \TEX.
+
+Does that mean that one cannot add some options to influence that tuning? For sure
+one can. The source has this comment:
+
+\startquotation
+ When looking for optimal line breaks, \TEX\ creates a \quote {break node} for
+ each break that is {\em feasible}, in the sense that there is a way to end a line
+ at the given place without requiring any line to stretch more than a given
+ tolerance. A break node is characterized by three things: the position of the
+ break (which is a pointer to a \type {glue_node}, \type {math_node}, \type
+ {penalty_node}, or \type {disc_node}); the ordinal number of the line that will
+ follow this breakpoint; and the fitness classification of the line that has just
+ ended, i.e., \type {tight_fit}, \type {decent_fit}, \type {loose_fit}, or \type
+ {very_loose_fit}.
+\stopquotation
+
+The book {\TEX\ by Topic} (by Eijkhout) gives a good explanation of the way lines
+are broken so there is no need to go into detail here. The code involved is not
+that trivial anyway. The criteria for deciding what is bad are as follows:
+
+\starttabulate[|c|c|c|]
+\FL
+\BC verdict \BC effect \BC badness \NC \NR
+\ML
+\NC very loose \NC stretch \NC >= 100 \NC \NR
+\NC loose \NC stretch \NC >= 13 \NC \NR
+\NC decent \NC \NC <= 12 \NC \NR
+\NC tight \NC shrink \NC >= 13 \NC \NR
+\LL
+\stoptabulate
+
+When the difference between two lines is more than one, they are considered to be
+visually incompatible. Then, if the badness of any line exceeds \type
+{pretolerance} a second pass is triggered, When \type {pretolerance} is negative
+the first pass is skipped. When the badness of any line exceeds \type {tolerance}
+a third pass is triggered and \type {emergencystretch} is used to make things fit.
+
+Where in traditional \TEX\ a lot of parsing, hyphenation, font handling and par
+building is combined, in \LUAMETATEX\ we always work with completely hyphenated
+and font readied lists. In traditional \TEX\ the first pass works on
+the original non|-|hyphenated lists.
+
+In the source there is an old note that one day I will play with a plugged in
+badness calculation but it also says that there might be a performance impact as
+well as all kind of unforeseen side effects because \TEX\ makes sure that the
+heuristics lead to values that don't result in overflow and such.
+
+Another note concerns more fitness values. Doing that will increase the runtime a
+little but on a modern machine that is not really an issue. Shortly after I
+upgraded my laptop to a somewhat newer one I decided to play with this and
+therefore any performance hit would go unnoticed anyway. The following snippet
+from the source shows the idea:
+
+\starttyping
+typedef enum fitness_value {
+ very_loose_fit, /*tex lines stretching more than their stretchability */
+ loose_fit, /*tex lines stretching 0.5 to 1.0 of their stretchability */
+ semi_loose_fit,
+ decent_fit, /*tex for all other lines */
+ semi_tight_fit,
+ tight_fit, /*tex lines shrinking 0.5 to 1.0 of their shrinkability */
+ n_of_finess_values
+} fitness_value;
+\stoptyping
+
+This means that when we loop over \type {very_loose_fit} upto \type {tight_fit}
+we have two more classes to take into account: the semi ones. Playing with that
+and associating them with magic numbers quickly learned that we enter the area of
+\quote {random improvements}. You can render variants and because some will look
+better and others worse one can argue for any case. And as usual, once a user
+(unaware of what we are doing) looks at it, things like successive hyphens, wider
+spaces, rivers and such are seen as the main difference. Of course spacing is the
+direct result of this kind of messing, but because the effects are actually
+mostly noticeable on non|-|justified texts it then is the end|-|of|-|line spacing
+that influences the verdict. \footnote {When \HZ\ showed up in \PDFTEX\ we did
+experiments with random samples of its usage and \TEX ies at user group meetings
+and the results were such that one could only draw the conclusion that on the
+average a user has no clue if something is good or bad for what reason. The
+strong emphasis in the \TEX\ community on hyphenation makes that an eye|-|catching
+criterium. So having two in a successive lines even when there is really no
+better solution is what draws the attention and users then tend to think that
+what a survey is about is \quotation {The quality of hyphenation related to
+breaking paragraphs into lines.}}
+
+In the end this kind of extensions make little sense. One can of course play
+science and introduce all kind of imaginary cases where it might work but that is
+why I started this summary by explaining what drives developments: users and
+constraints. Playing science for the sake of it is pseudo science. And, as with
+much science related to typesetting (probably with the exception of Don's work)
+most has therefore little practical value.
+
+So, do we keep this feature or not? We actually do, if only to be able to
+demonstrate the fuzziness of this. We have an undocumented magic parameter:
+
+\starttyping
+\linebreakcriterium"0C0C0C63
+\stoptyping
+
+Actually the value is zero but when one of the four byte pairs is zero it will
+default to \type {"0C} (\number"0C) or \type {"63} (\number"63). The values
+concern \type {semitight}, \type {decent}, \type {semiloose}, and \type {loose}.
+After some trial and error I got to the examples on the next two pages. You need
+to zoom in to see the differences (the black one is the original). In setting used are:
+
+\starttabulate[|c|c|l|]
+\BC \BC \type {\hsize} \BC \type {\setupalign} \NC \NR
+\NC 1 \NC 12em \NC normal, stretch, tolerant \NC \NR
+\NC 2 \NC 18em \NC flushleft \NC \NR
+\stoptabulate
+
+As mentioned, one can look at specific expected properties and draw conclusions
+but when \TEX\ cannot find a good solution using its default, it is unlikely that
+alternative settings help you out, unless you do that on a per|-|paragraph basis.
+
+% run in default font and layout
+
+\startbuffer[lbc]
+\def\TestA#1#2#3%
+ {\switchtobodyfont[10pt]%
+ \ruledvtop
+ {\hsize#1\relax
+ \begingroup
+ \setupalign[#2]%
+ \linebreakcriterium"#3\relax
+ \samplefile{tufte}\par
+ \endgroup
+ \hpack to \hsize{\hss\infofont\setstrut\strut\black\string\linebreakcriterium="#3\hss}}}
+
+\def\TestB#1#2%
+ {\startTEXpage[offset=4dk]
+ \hbox \bgroup
+ {\black \TestA{#1}{#2}{00000000}}\kern1ex
+ {\red \TestA{#1}{#2}{00001C00}}\kern1ex
+ {\green \TestA{#1}{#2}{00002C00}}\kern1ex
+ {\blue \TestA{#1}{#2}{00003C00}}\kern1ex
+ {\cyan \TestA{#1}{#2}{00004C00}}\kern1ex
+ {\magenta\TestA{#1}{#2}{00005C00}}
+ \egroup
+ \vskip1ex
+ \hbox \bgroup
+ \startoverlay {\TestA{#1}{#2}{00000000}} \stopoverlay \kern1ex
+ \startoverlay {\TestA{#1}{#2}{00000000}} {\red \TestA{#1}{#2}{00001C00}} \stopoverlay \kern1ex
+ \startoverlay {\TestA{#1}{#2}{00000000}} {\green \TestA{#1}{#2}{00002C00}} \stopoverlay \kern1ex
+ \startoverlay {\TestA{#1}{#2}{00000000}} {\blue \TestA{#1}{#2}{00003C00}} \stopoverlay \kern1ex
+ \startoverlay {\TestA{#1}{#2}{00000000}} {\cyan \TestA{#1}{#2}{00004C00}} \stopoverlay \kern1ex
+ \startoverlay {\TestA{#1}{#2}{00000000}} {\magenta\TestA{#1}{#2}{00005C00}} \stopoverlay
+ \egroup
+ \stopTEXpage}
+
+\TestB{12em}{normal,stretch,tolerant}
+\TestB{18em}{flushleft}
+\stopbuffer
+
+\startpagemakeup[pagestate=start,doublesided=no,page=no]
+ \centerbox {\typesetbuffer[lbc][page=1,frame=on,height=\dimexpr\textwidth-2ex\relax,orientation=90]}
+\stoppagemakeup
+\startpagemakeup[pagestate=start,doublesided=no,page=no]
+ \centerbox {\typesetbuffer[lbc][page=2,frame=on,width=\dimexpr\textheight-2ex\relax,orientation=90]}
+\stoppagemakeup
+
+\stopchapter
+
+\stopcomponent
+
diff --git a/doc/context/sources/general/manuals/ontarget/ontarget-makessense.tex b/doc/context/sources/general/manuals/ontarget/ontarget-makessense.tex
new file mode 100644
index 000000000..e0a635285
--- /dev/null
+++ b/doc/context/sources/general/manuals/ontarget/ontarget-makessense.tex
@@ -0,0 +1,110 @@
+% language=us runpath=texruns:manuals/ontarget
+
+\startcomponent ontarget-makessense
+
+\environment ontarget-style
+
+\startchapter[title={But this does}]
+
+In \LUAMETATEX\ one can do a lot on \LUA, like what I will discuss next, but
+because it is somewhat fundamental it became a core feature of the engine. It was
+also quite easy to implement. It has to do with packaging. \footnote {I actually
+did prototype it in \LUA\ first but wanted a more natural integration in the
+end.}
+
+The box constructors in traditional \TEX\ accept two keywords: \type {to} for
+setting an exact width and \type {spread} for specifying additional width. In
+\LUAMETATEX\ we have some more like \type {shift} (a traditional \TEX\ concept),
+\type {orientation}, \type {xmove}, \type {xoffset}, \type {ymove} and \type
+{yoffset} for absolute positioning, \type {anchor(s)}, \type {target} and \type
+{source} for relative positioning, \type {axis} and \type {class} for usage in
+\math, \type {delay} for leader like boxes, the multiple \type {attr} key for
+setting attributes, a special subtype directive \type {container} and \type
+{direction} for controlling bidirectional typesetting, and \type {reverse} for
+reversing content. The latest addition: \type {adapt} is there for controlling
+and freezing glue.
+
+So, in addition to the width related keys \type {to} and \type {spread} we have
+\type {adapt} that drives wo what width the box will be typeset. \footnote {For
+the moment this keyword only has effect for horizontal boxes.} The keyword is
+followed by a scale values between -1000 and 1000 where a negative value enforces
+shrink and a positive value stretch. The following table shows the effects:
+
+\startbuffer
+\starttabulate
+ \Test{}
+ \Test{to 4cm}
+ \Test{to \hsize}
+ \Test{spread 1cm}
+ \Test{spread -1cm}
+ \Test{adapt -1000}
+ \Test{adapt -750}
+ \Test{adapt -500}
+ \Test{adapt 0}
+ \Test{adapt 500}
+ \Test{adapt 750}
+ \Test{adapt 1000}
+\stoptabulate
+\stopbuffer
+
+\def\Test#1{%
+ \NC
+ \type {#1}
+ \NC
+ \showglyphs
+ \ruledhbox#1{Here are just some words so that we can see what happens.}%
+ \NC \NR
+}
+
+\getbuffer
+
+When a box is typeset the natural glue width is used but when the required width
+exceeds the natural width the glue stretch components kick in. With a negative
+spread the shrink is used but you can get underflows. The \type {adapt} feature
+freezes the glue and it removes the stretch and shrink after applying it to the
+glue width with the given scale factor. So, in order to get the minimum width you
+use \type {adapt -1000}.
+
+\def\Test#1{%
+ \NC
+ \type {#1}
+ \NC
+ \medmuskip 4mu plus 2mu minus 2mu\relax
+ \showmakeup[mathglue]%
+ \showglyphs
+ \ruledhbox#1{$ x + x + a = 2x + a$\hss}%
+ \NC \NR
+}
+
+The reason why I decided to add this feature is that when experimenting with math
+alignments I wanted to be able to see what shrink could be achieved. \footnote
+{At that time Mikael and I were experimenting with consistent spacing in math
+alignments.} The next example shows this:
+
+\getbuffer
+
+Once we had this new feature it made sense to add support for it to \type
+{\framed}, one of the oldest macros that got extended over time:
+
+\startbuffer
+\inframed[adaptive=1000] {Just some words}
+\inframed[adaptive=500] {Just some words}
+\inframed[adaptive=0] {Just some words}
+\inframed[adaptive=-500] {Just some words}
+\inframed[adaptive=-1000]{Just some words}
+\stopbuffer
+
+\typebuffer
+
+This renders as:
+
+\startlinecorrection \getbuffer \stoplinecorrection
+
+Once we have it there other mechanisms can benefit from it, for instance natural
+tables. But keep in mind that spaces are fixed in there so there is only the
+expected result if glue has stretch or shrink.
+
+\stopchapter
+
+\stopcomponent
+
diff --git a/doc/context/sources/general/manuals/ontarget/ontarget-math.tex b/doc/context/sources/general/manuals/ontarget/ontarget-math.tex
index 50e5dff5f..83aae8bcd 100644
--- a/doc/context/sources/general/manuals/ontarget/ontarget-math.tex
+++ b/doc/context/sources/general/manuals/ontarget/ontarget-math.tex
@@ -1149,6 +1149,15 @@ experience. \footnote {Whenever I look at (my) old (math) school books I realize
that Don Knuth had very good reasons to come up with \TEX\ and, it being hard to
beat, \TEX\ still sets the standard!}
+As we mention class specific options, we also need to mention the special case
+where we have for instance simple formulas like single atoms (for instance
+digits) are preceded by a sign (binary). These special spacing cases are handled
+by a lookahead flag that can be set \typ {\setmathoptions <class>}, like the
+slack flags. More options might become available in due time. When set the
+lookahead will check for the automatically injected end class atom and use that
+for spacing when found. The mentioned lookahead is one of the hard coded
+heuristics in the traditional engine but here we need to explicitly configure it.
+
\stopsubject
\startsubject[title=Ghosts]
@@ -1770,6 +1779,232 @@ look again at this.
\stopsubject
+\startsubject[title=Normalization]
+
+Once we had all these spacing related features upgraded it was time to move to
+other aspects math typesetting. Most of that is not handled in the engine but at
+the macro level. Examples of this are making sure that math spacing obeys the
+rules across alignment cells, breaking long formulas into lines with various
+alignment schemes. The first is accommodated by using the primitives that set the
+states at the beginning and end of a formula so that is definitely something that
+the engine facilitates. The second was already possible in \MKIV\ but is somewhat
+more transparent now by using tagged boundary nodes.
+
+But for this summary we stick to discussing the more low level features and where
+most of what we discussed here concerns horizontal spacing we also have some
+vertical magic like the mentioned scaled fences and operators but they sort of
+behave as expected given the traditional \TEX\ approach. We have some more:
+
+\startbuffer
+\definemathradical[esqrt][sqrt][height=\maxdimen,depth=\maxdimen]
+\definemathradical[ssqrt][sqrt][height=3ex,depth=2ex]
+
+\def\TestSqrt#1%
+ {test $ #1{x} + #1{\sin(x)} $ test\quad
+ test $ #1{x} + #1{\sin(x)} + #1{\frac{1}{x}} $ test\quad
+ test $ #1{x} + #1{x^2} $ test\quad
+ test $ \left(#1{x} + #1{x^2} \right) $ test\par}
+
+\TestSqrt \sqrt \blank
+\TestSqrt \esqrt \blank
+\TestSqrt \ssqrt \blank
+\stopbuffer
+
+\typebuffer \getbuffer
+
+In the above example you see that square roots can be made to adapt themselves to
+other such roots. For this we had to add an additional pass. Originally there are
+just two passes: a first typesetting pass where the maximum height and depth are
+collected so that in the second pass the fences can be generated and injected.
+That second pass also handles the spacing and penalties. In \LUAMETATEX\ we now
+have (1) radical body typesetting, (2) radical typesetting, (3) atom typesetting
+with height and depth analysis, (4) fence typesetting, and finally (5) inject
+spacing, penalties, remove slack, etc.
+
+In the examples above we set the height and depth and these are passed by
+keywords to the radical primitive (most atoms and math structures accept keywords
+that control rendering). Here the special values \type {\maxdimen} signal that we
+have to make radicals of equal height and depth.
+
+In \MKII\ we had ways to snap formulas so that we got consistent line spacing.
+For a while I wondered if the engine could help with that but in the end no
+specific engine features are needed, but is is definitely an area that I keep an
+eye on because consistent spacing is important. After all one has to draw aline
+somewhere and we always have the \LUA\ callback mechanism available.
+
+\stopsubject
+
+\startsubject[title=More goodies]
+
+This summary will never be complete because we keep improving the rendering of
+math. For instance, when Mikael checked some less used math alphabets of Latin
+Modern and Bonum, as part of the goodie file completion, we were a bit horrified
+by the weird top accent anchoring, inconsistent dimensions and stale italic
+correction present in some glyphs. For instance there was a italic correction
+after an upright blackboard lowercase \quote {f}, the upright digits had somewhat
+random top accent anchors, and due to the lack of granularity in for instance
+wide hats, characters that are often seen together got inconsistent wide hats.
+Also clashing with scripts was possible. All this resulted in yet another bunch
+of features:
+
+\startitemize
+\startitem
+ In the goodie files we added efficient options to remove anchors from
+ alphabets (or individual characters).
+\stopitem
+\startitem
+ In the goodie files we added similar options to remove italic correction.
+\stopitem
+\startitem
+ Characters got a few extra fields: margins that can be used to cheat with
+ dimensions so that we can get more consistent wide accents.
+\stopitem
+\startitem
+ The engine also got the possibility to compensate for accents when
+ superscripts need to be anchored (by diminishing the height of accents as
+ well as via an offsets).
+\stopitem
+\stopitemize
+
+We expect to add (and use) some more options like this when we run into other
+persistent issues. For sure there are some already that are not discussed here.
+Of course one can argue why we spend time on this: in 15 years of \UNICODE\ math
+usage in the \TEX\ community no one ever bothered about a wide hat over the
+digit~7 and no one wondered about the bad spacing after a lowercase blackboard~f,
+but as we go on we do run into these phenomena and it has become a bit of an
+obsession to get it all right. \footnote {Of course all this puts the usual
+bashing of Microsoft Word by users in a different perspective: limited control in
+the \TEX\ engine, faulty fonts that come with \TEX\ distributions, lack of
+testing and quality control, and probably the believe that all gets done well
+automatically plays a role here.}
+
+By closely looking at default positioning of accents on top of characters Mikael
+noticed that the anchor points are actually always in the middle of the topmost
+left and right points of shapes. It looks like these points are calculates
+automatically and therefore you end up with an anchor on top of the highest part
+of the seven in Latin Modern Serif but in the middle of a seven with a flat top.
+You also get anchors at the top of the vertical line in b, d, and on the sticky
+bit of the g. It is a good example of being careful with automating font design.
+In our case, removing most anchors and adding a few later on was the solution.
+\footnote {In the original fonts and traditional \TEX\ engine a kerning pair
+between a so called skew char and the character at hand is used.}
+
+\stopsubject
+
+\startsubject[title=Untold stories]
+
+There are of course more features but not all make sense to discuss here. For instance,
+all hard coded properties are now configurable. Take for instance:
+
+\startbuffer
+\Umathsuperscriptvariant\textstyle 1
+\Umathsubscriptvariant \textstyle 1
+
+$ 1_2^3 \quad {\scriptstyle 1_2^3} \quad {\displaystyle 1_2^3}$
+\stopbuffer
+
+\typebuffer
+
+This gives us:
+
+\startlinecorrection
+\scale[scale=3000]{\getbuffer}
+\stoplinecorrection
+
+Here the number refers to one of the build in variants, that themselves are a
+range of styles. In the next table the narrow variants are cramped:
+
+\def\Cramped#1{{\glyphyscale\numexpr6*\glyphyscale/10\relax#1}}
+
+\starttabulate[|c|l|c|c|c|c|c|c|c|c|]
+\BC 0 \BC normal \NC
+ D \NC \Cramped{D} \NC
+ T \NC \Cramped{T} \NC
+ S \NC \Cramped{S} \NC
+ SS \NC \Cramped{SS} \NC
+\NR
+\BC 1 \BC cramped \NC
+ \Cramped{D} \NC \Cramped{D} \NC
+ \Cramped{T} \NC \Cramped{T} \NC
+ \Cramped{S} \NC \Cramped{S} \NC
+ \Cramped{SS} \NC \Cramped{SS} \NC
+\NR
+\BC 2 \BC subscript \NC
+ \Cramped{S} \NC \Cramped{S} \NC
+ \Cramped{S} \NC \Cramped{S} \NC
+ \Cramped{SS} \NC \Cramped{SS} \NC
+ \Cramped{SS} \NC \Cramped{SS} \NC
+\NR
+\BC 3 \BC superscript \NC
+ S \NC S \NC
+ S \NC S \NC
+ SS \NC SS \NC
+ SS \NC SS \NC
+\NR
+\BC 4 \BC small \NC
+ S \NC S \NC
+ S \NC S \NC
+ SS \NC SS \NC
+ SS \NC SS \NC
+\NR
+\BC 5 \BC smaller \NC
+ S \NC \Cramped{S} \NC
+ S \NC \Cramped{S} \NC
+ SS \NC \Cramped{SS} \NC
+ SS \NC \Cramped{SS} \NC
+\NR
+\BC 6 \BC numerator \NC
+ S \NC \Cramped{S} \NC
+ S \NC \Cramped{S} \NC
+ SS \NC \Cramped{SS} \NC
+ SS \NC \Cramped{SS} \NC
+\NR
+\BC 7 \BC denominator \NC
+ \Cramped{S} \NC \Cramped{S} \NC
+ \Cramped{S} \NC \Cramped{S} \NC
+ \Cramped{SS} \NC \Cramped{SS} \NC
+ \Cramped{SS} \NC \Cramped{SS} \NC
+\NR
+\BC 8 \BC double (superscript) \NC
+ S \NC \Cramped{S} \NC
+ S \NC \Cramped{S} \NC
+ SS \NC \Cramped{SS} \NC
+ SS \NC \Cramped{SS} \NC
+\NR
+\stoptabulate
+
+If you want you can change these values but of course we're then basically
+changing some of logic behind math rendering and for sure Don Knuth had good
+reasons for these defaults.
+
+Another untold story relates to multi scripts. When a double script is seen,
+\TEX\ injects an ordinary recovery atom, issues an error message, and when told
+so just continues. In order to always continue \LUAMETATEX\ introduces a mode
+variable that default to minus one, as negative values will trigger the error.
+Zero of positive values are interpreted as a class and bypass the error. Here is
+an example of usage:
+
+\startbuffer
+\mathdoublescriptmode
+ "\tohexadecimal\mathexperimentalcode % experimental class
+ \tohexadecimal\mathexperimentalcode % we have to set both left and right
+
+\setmathspacing \mathexperimentalcode \mathexperimentalcode \allmathstyles 20mu
+\setmathspacing \mathordinarycode \mathexperimentalcode \allmathstyles 20mu
+
+$x^1_2^3_4^^5__6^^7__8$
+\stopbuffer
+
+\typebuffer
+
+We get this:
+
+\startlinecorrection
+\scale[scale=3000]{\getbuffer}
+\stoplinecorrection
+
+\stopsubject
+
\startsubject[title=Final words]
One can argue that all these new features can make a document look better. But
@@ -1791,14 +2026,30 @@ handle math. One can also wonder in what way massive remote editing as well as
collaborative working on documents make things better. It probably becomes less
personal. At meetings and platforms \TEX\ users like to bash the alternatives but
in the end they are part of the same landscape and when it comes to math they
-dominate. Maybe there is less to bragg about then we like: just do your thing and
+dominate. Maybe there is less to brag about then we like: just do your thing and
try to do it as good as possible. Rely on your eyes and pay attention to the
details, which is possible because the engine provided the means. The previous
text shows a few things to pay attention to.
-Once all the basics that have to do with proper dimensions, spacing, penalties
-and logic are dealt with, we will move on to the more high level constructs. So,
-expect more.
+Now that all the basics that have to do with proper dimensions, spacing,
+penalties and logic are dealt with, we moved on to the more high level
+constructs. We also haven't applied some features in the \CONTEXT\ code base yet
+and are now experimenting with the more high level constructs. For instance the
+frequently used math alignment mechanism has been overhauled to support advanced
+inter atom spacing across rows, and in practice one will now more often not even
+use this alignment mechanism and use the alignment features in multi|-|line
+display math, if only because they offer advanced annotation. As a nice side
+effect some of the mechanism that we use for this (like the improved \type
+{\vadjust} primitive engine feature) also became somewhat more powerful in
+regular text mode and we'll see where that brings us.
+
+Given the time we spend on this and given the numerous new features it will take
+a while before all that got added to the engine will be documented. Of course the
+usage in \CONTEXT\ also serves as documentation. This is not really a problem
+because most users will happily rely on the goodie files being okay and
+maintained, and usage other than \CONTEXT\ is unlikely to use these new features,
+if only because it will break away from the established long term standards and
+habits.
\stopsubject
@@ -1900,3 +2151,29 @@ expect more.
% $ \eq \not $\par % gets collapsed
% example: a_1=b_1+c_1 (for spacing)
+
+
+% \startbuffer
+% We test \dorecurse{20}{$x^{#1}$ and $\frac{1}{#1}^x$ and $\sqrt[#1]{x}$ and }that's it.
+% \stopbuffer
+%
+% \startpostponing
+% \startcombination[nx=2,ny=3,location=top]
+% {\ruledvbox{\hsize.45\textwidth \setupformula[snap=no] \showboxes \enabletrackers [math.snapping=darkred] \getbuffer}} {}
+% {\ruledvbox{\hsize.45\textwidth \setupformula[snap=no] \disabletrackers[math.snapping] \getbuffer}} {}
+% {\ruledvbox{\hsize.45\textwidth \setupformula[snap=yes,snapstep=small] \showboxes \darkgreen \enabletrackers [math.snapping=darkred] \getbuffer}} {}
+% {\ruledvbox{\hsize.45\textwidth \setupformula[snap=yes,snapstep=small] \darkgreen \disabletrackers[math.snapping] \getbuffer}} {}
+% {\ruledvbox{\hsize.45\textwidth \setupformula[snap=yes,snapstep=big] \showboxes \darkblue \enabletrackers [math.snapping=darkred] \getbuffer}} {}
+% {\ruledvbox{\hsize.45\textwidth \setupformula[snap=yes,snapstep=big] \darkblue \disabletrackers[math.snapping] \getbuffer}} {}
+% \stopcombination
+% \stoppostponing
+
+
+% https://yurichev.com/mirrors/knuth1989.pdf .. DEK:
+%
+% I too had trouble with numerators and denominators: change no. 229 increased the
+% amount of space surrounding the bar line in displayed fractions, and I should have
+% made a similar change to fractions in text. (Page 68 of the new Volume 2 turned out
+% to be extremely ugly because of badly spaced fractions.) T~x82 was able to improve
+% the situation because of my experiences with T~x78, but even today I must take
+% special precautions in my TEX documents to get certain square roots to look right.
diff --git a/doc/context/sources/general/manuals/ontarget/ontarget-metapost.tex b/doc/context/sources/general/manuals/ontarget/ontarget-metapost.tex
new file mode 100644
index 000000000..521b90b63
--- /dev/null
+++ b/doc/context/sources/general/manuals/ontarget/ontarget-metapost.tex
@@ -0,0 +1,755 @@
+% language=us runpath=texruns:manuals/ontarget
+
+% Musical timestamp: while adding this to the engine and I listened to many John
+% Medeski (Martin and Wood) concert videos, many several times ... it kept me in
+% the flow!
+%
+% This wrapup was written with Dave Matthews Band - Seek Up - LIVE, 12/2/2018 in
+% the background, as I like these live acts.
+%
+% This is just a summary from my point of view. A real article is written by
+% Mikael Sundqvist who also explains how arctime and its companions actually
+% work.
+
+\startcomponent ontarget-metapost
+
+\environment ontarget-style
+
+\startchapter[title={To the point}]
+
+In the 2022 \NTG\ \MAPS\ 53 there is a visual very attractive article about
+generative graphics with \METAPOST\ by Fabrice Larribe. These graphics actually
+use very little \METAPOST\ code that use randomized paths and points and the
+magic is in getting the parameters right. This means that one has to process them
+a lot to figure out what looks best. Here is an example of such a graphic
+definition. I will show more variants so a rendering happens later on.
+
+\startbuffer
+\startMPdefinitions
+ vardef agitate_a(expr thepath, S, n, fn, t, ft) =
+ save R, nbpoints, noiselevel, rlength ;
+ path R ; nbpoints := n ; noiselevel := t ;
+ R := thepath ;
+ for s=1 upto S :
+ nbpoints := nbpoints * fn ;
+ noiselevel := noiselevel * ft ;
+ R := for i=1 upto nbpoints:
+ point (i/nbpoints) along R
+ randomized noiselevel
+ ..
+ endfor cycle ;
+ endfor ;
+ R
+ enddef ;
+\stopMPdefinitions
+\stopbuffer
+
+\typebuffer[option=tex] \getbuffer
+
+I will not explain the working of this because there is the article. Instead, I
+will focus on something that came up when the \MAPS\ was prepared: performance.
+Not only are these graphics large (which is no real problem) but they also take a
+while to render (which is something that does matter when one wants to find the
+best a parameters). For the first few variants we keep the same names of
+variables as in the article.
+
+\startbuffer[final:definition]
+\startMPdefinitions
+ vardef agitator(expr pth, iterations, points, pointfactor, noise, noisefactor) =
+ save currentpath, currentpoints, currentnoise ; path currentpath ;
+ currentpath := pth ;
+ currentpoints := points ;
+ currentnoise := noise ;
+ for step = 1 upto iterations :
+ currentpath := arcpointlist currentpoints of currentpath ;
+ if currentnoise <> 0 :
+ currentpath :=
+ for i within currentpath :
+ pathpoint
+ randomized currentnoise
+ ..
+ endfor
+ cycle ;
+ fi
+ currentnoise := currentnoise * noisefactor ;
+ currentpoints := currentpoints * pointfactor ;
+ endfor ;
+ currentpath
+ enddef ;
+\stopMPdefinitions
+\stopbuffer
+
+\startbuffer[final:graphic]
+\startMPcode
+ path pth ;
+ nofcircles := 15 ; iterations := 10 ;
+ points := 10 ; pointfactor := 1.3 ;
+ noise := 5 ; noisefactor := 0.8 ;
+
+ nofcircles := 5 ; iterations := 10 ;
+ points := 5 ; pointfactor := 1.3 ;
+
+% for c = nofcircles downto 1 :
+% pth := fullcircle scaled (c * 6.5) scaled 3 ;
+% points := floor(arclength(pth) * 0.5) ;
+% pth := agitator(pth, iterations, points, pointfactor, noise, noisefactor) ;
+% eofill pth
+% withcolor darkred
+% withtransparency(1,4/nofcircles) ;
+% draw pth
+% withpen pencircle scaled 0.1
+% withtransparency(1,4/nofcircles) ;
+% endfor ;
+
+% currentpicture := currentpicture xsized TextWidth ;
+
+ for c = nofcircles downto 1 :
+ pth := fullcircle scaled (c * 6.5) scaled 3 ;
+ points := floor(arclength(pth) * 0.5) ;
+ pth := agitator(pth, iterations, points, pointfactor, noise, noisefactor) ;
+ draw pth
+ withpen pencircle scaled 1
+ withcolor (c/nofcircles)[darkgreen,darkred] ;
+ endfor ;
+
+ currentpicture := currentpicture xsized .5TextWidth ;
+\stopMPcode
+\stopbuffer
+
+\startplacefigure
+ [title={Fabrice's agitated circles, with reduced properties to keep this file small (see source).},
+ reference=fig:agitated]
+ \getbuffer[final:definition,final:graphic]
+\stopplacefigure
+
+In \in {figure} [fig:agitated] we show the (kind of) graphic that we are dealing
+with. Such an agitator is used in a loop so that we agitate multiple circles,
+where we go from large to small with for instance 4868, 4539, 4221, 3892, 3564,
+3245, 2917, 2599, 2270, 1941, 1623, 1294, 966, 647 and 319 points. The article
+uses a definition like below for the graphic where you can see the agitator being
+applied to each of the circles.
+
+\starttyping[option=mp,color=]
+path P ; numeric NbCircles, S, nzero, fn, tzero, ft ;
+
+randomseed := 10 ;
+defaultscale := .05 ;
+
+NbCircles := 15 ; S := 10 ; nzero := 10 ; fn := 1.3 ; tzero := 5 ; ft := 0.8 ;
+
+for c = NbCircles downto 1 :
+ P := fullcircle scaled (c*6.5) scaled 3 ;
+ P := agitate_a(P, S, nzero, fn, tzero, ft) ;
+ eofill P
+ withcolor transparent(1,4/NbCircles,col) ;
+ draw P
+ withpen pencircle scaled 0.1
+ transparent(1,4/NbCircles,.90[black,col]) ;
+endfor ;
+\stoptyping
+
+The first we noticed is that the graphics processes faster when double mode is
+used: we gain 40--50\percent\ and the reason for this is that modern processors
+are very good at handling doubles while \METAPOST\ in scaled mode has to do a lot
+of juggling with pseudo fractions. In the timings shown later we leave that
+improvement out. Also, because of this observation \CONTEXT\ \LMTX\ now defaults
+its \METAPOST\ instances to method double.
+
+When I stared at the agitator code I noticed that the \type {along} macro was
+used. That macro returns a point at given percentage along a path. In order to do
+that the macro calculates the length of the path and then locates that point. The
+primitive operations involved are \type {arclength}, \type {arctime of} and \type
+{point of} and each these takes some time to complete. A first improvement is to
+inline the \type {along} and hoist the length calculation outside the loop.
+
+\startbuffer
+\startMPdefinitions
+ vardef agitate_b(expr thepath, S, n, fn, t, ft) =
+ save R, nbpoints, noiselevel, rlength ;
+ path R ; nbpoints := n ; noiselevel := t ;
+ R := thepath ;
+ for s=1 upto S :
+ nbpoints := nbpoints * fn ;
+ noiselevel := noiselevel * ft ;
+ rlength := (arclength R) / nbpoints;
+ R := for i=1 upto nbpoints:
+ (point (arctime (i * rlength) of R) of R)
+ randomized noiselevel
+ ..
+ endfor cycle ;
+ endfor ;
+ R
+ enddef ;
+\stopMPdefinitions
+\stopbuffer
+
+\typebuffer[option=tex] \getbuffer
+
+There is not that much that we can improve here but because Mikael Sundqvist and
+I had just extended \METAPOST\ with some intersection improvements, it made sense
+to see what we could do in the engine. In the next variant the \type {arcpoint}
+combines \type {arctime of} and \type {point of}. The reason this is much
+faster is that we are already on the right spot when we got the time, and we save
+a sequential \type {point of} lookup, something that takes more time when paths
+are longer.
+
+\startbuffer
+\startMPdefinitions
+ vardef agitate_c(expr thepath, S, n, fn, t, ft) =
+ save R, nbpoints, noiselevel, rlength ;
+ path R ; nbpoints := n ; noiselevel := t ;
+ R := thepath ;
+ for s=1 upto S :
+ nbpoints := nbpoints * fn ;
+ noiselevel := noiselevel * ft ;
+ rlength := (arclength R) / nbpoints;
+ R := for i=1 upto nbpoints:
+ (arcpoint (i * rlength) of R)
+ randomized noiselevel
+ ..
+ endfor cycle ;
+ endfor ;
+ R
+ enddef ;
+\stopMPdefinitions
+\stopbuffer
+
+\typebuffer[option=tex] \getbuffer
+
+At that stage we wondered if we could come up with a primitive like \typ
+{intersectiontimelist} for these points; here a list refers to a path in which we
+collect the points. Now, as with the intersection primitives, \METAPOST\ loops
+over the segments of a path and works within such a segment. That is why the
+following variant has an explicit start at point zero: we can now use offsets
+(discrete points).
+
+\startbuffer
+\startMPdefinitions
+ vardef agitate_d(expr thepath, S, n, fn, t, ft) =
+ save R, nbpoints, noiselevel, rlength ;
+ path R ; nbpoints := n ; noiselevel := t ;
+ R := thepath ;
+ for s=1 upto S :
+ nbpoints := nbpoints * fn ;
+ noiselevel := noiselevel * ft ;
+ rlength := (arclength R) / nbpoints;
+ R := for i=1 upto nbpoints:
+ (arcpoint (0, i * rlength) of R)
+ randomized noiselevel
+ ..
+ endfor cycle ;
+ endfor ;
+ R
+ enddef ;
+\stopMPdefinitions
+\stopbuffer
+
+\typebuffer[option=tex] \getbuffer
+
+During an evening zooming Mikael and I figured out, by closely looking at the
+source, how the arc functions work and how we could indeed come up with a list
+primitive. The main issue was to use the right information. Mikael sat down to
+make a pure \METAPOST\ variant and I hacked the engine. Mikael came up with a
+first variant similar to the following, where we use a new primitive \typ
+{subarclength}.
+
+\startbuffer
+\startMPdefinitions
+ vardef arcpoints_a(expr thepath, cnt) =
+ save len, seg, tot, tim, stp, acc ;
+ numeric len ; len := length thepath ;
+ numeric seg ; seg := 0 ;
+ numeric tot ; tot := 0 ;
+ numeric tim ; tim := 0 ;
+ %
+ numeric acc[] ; acc[0] := 0 ;
+ for i = 1 upto len:
+ acc[i] := acc[i-1] + subarclength (i-1,i) of thepath ;
+ endfor;
+ %
+ numeric stp ; stp := acc[len] / cnt;
+ %
+ point 0 of thepath
+ for tot = stp step stp until acc[len] :
+ hide(
+ forever :
+ exitif ((tim < tot) and (tot < acc[seg+1])) ;
+ seg := seg + 1 ;
+ tim := acc[seg] ;
+ endfor ;
+ )
+ -- (arcpoint (seg,tot-tim) of thepath)
+ endfor if cycle thepath : -- cycle fi
+ enddef ;
+\stopMPdefinitions
+\stopbuffer
+
+\typebuffer[option=tex] \getbuffer
+
+Getting points of a path is somewhat complicated by the fact that the length of a
+closed path is different from that of an open path even if they have the same
+number of so-called knots. Internally a path is always a closed loop. That way,
+when \METAPOST\ runs over a path, it can easily access the first point when it's
+at the end, something that is handy when that point has to be taken into account.
+Therefore, the end condition of a loop over a path is the arrival at the
+beginning. In the next graphic we show a bit how these first (zero) and last
+points are located. One reason why the previous macros start at point one and not
+at zero is that \type {arclength} can overflow due to the randomly growing path
+otherwise.
+
+\startlinecorrection
+\startMPcode
+ path p ; p := ((0,0) -- (1,0) -- (1,1) -- (0,1)) xyscaled (20EmWidth,5LineHeight) ;
+ path q ; q := p -- cycle ;
+
+ draw p withpen pencircle scaled 4mm withcolor .2white ;
+ draw q withpen pencircle scaled 2mm withcolor .6white ;
+
+ draw point length(p) of p withpen pencircle scaled 6mm withcolor green;
+ draw point length(q) of q withpen pencircle scaled 6mm withcolor blue ;
+
+ draw point 0 of p withpen pencircle scaled 4mm withcolor red ;
+ draw point 0 of q withpen pencircle scaled 2mm withcolor yellow ;
+
+ draw textext.lft("\strut\tttf point length of p") shifted (point length(p) of p) shifted (-6mm,0) ;
+ draw textext.lft("\strut\tttf point length of q") shifted (point length(q) of q) shifted (-6mm,LineHeight) ;
+ draw textext.lft("\strut\tttf point 0 of p") shifted (point 0 of p) shifted (-6mm,0) ;
+ draw textext.lft("\strut\tttf point 0 of q") shifted (point 0 of q) shifted (-6mm,-LineHeight) ;
+
+ draw textext("\strut\tttf p is open (dark)") shifted (center p) shifted (0, LineHeight/2) ;
+ draw textext("\strut\tttf q is closed (light)") shifted (center q) shifted (0,-LineHeight/2) ;
+\stopMPcode
+\stoplinecorrection
+
+The difference between starting at zero or one for a cycle is show below, we get
+more and more points!
+
+\startlinecorrection
+\startMPcode
+ path p ; p := fullsquare ; path q ;
+
+ for i=1 upto 100 :
+ q := for j=1 upto length(p) : (point j of p) -- endfor cycle ;
+ p := q ;
+ endfor ;
+
+ draw p scaled 2cm withpen pencircle scaled 1mm withcolor "darkred" ;
+ drawpointlabels p scaled 2cm ;
+
+ path p ; p := fullsquare shifted (3/2,0) ; path q ;
+
+ for i=1 upto 100 :
+ q := for j=0 upto length(p) : (point j of p) -- endfor cycle ;
+ p := q ;
+ endfor ;
+
+ draw p scaled 2cm withpen pencircle scaled 1mm withcolor "darkred" ;
+ drawpointlabels p scaled 2cm ;
+\stopMPcode
+\stoplinecorrection
+
+% point of
+%
+% if (mp_left_type(p) == mp_endpoint_knot) {
+% set_number_to_unity(n);
+% number_negate(n);
+% } else {
+% set_number_to_zero(n);
+% }
+% do {
+% p = mp_next_knot(p);
+% number_add(n, unity_t);
+% } while (p != cur_exp_knot);
+
+% length:
+%
+% mp_knot p = cur_exp_knot;
+% int l = mp_left_type(p) == mp_endpoint_knot ? -1 : 0;
+% do {
+% p = mp_next_knot(p);
+% ++l;
+% } while (p != cur_exp_knot);
+% set_number_from_int(*n, l);
+
+In the next variants we will not loop over points but step to the \type
+{arclength}. Watch the new \type {subarclength} primitive that starts at an
+offset. This is much faster than taking a \type {subpath of}. We can move the
+accumulator loop into the main loop:
+
+\startbuffer
+\startMPdefinitions
+ vardef arcpoints_b(expr thepath, cnt) =
+ save len, aln, seg, tot, tim, stp, acc ;
+ numeric len ; len := length thepath ;
+ numeric aln ; aln := arclength thepath ;
+ numeric seg ; seg := 0 ;
+ numeric tot ; tot := 0 ;
+ numeric tim ; tim := 0 ;
+ numeric stp ; stp := aln / cnt;
+ numeric acc ; acc := subarclength (0,1) of thepath ;
+ %
+ point 0 of thepath
+ for tot = stp step stp until aln :
+ hide(
+ forever :
+ exitif tot < acc ;
+ seg := seg + 1 ;
+ tim := acc ;
+ acc := acc + subarclength (seg,seg+1) of thepath ;
+ endfor ;
+ )
+ -- (arcpoint (seg,tot-tim) of thepath)
+ endfor if cycle thepath : -- cycle fi
+ enddef ;
+\stopMPdefinitions
+\stopbuffer
+
+\typebuffer[option=tex] \getbuffer
+
+If you don't like the \type {hide} the next variant also works okay:
+
+\startbuffer
+\startMPdefinitions
+ vardef mfun_arc_point(text tot)(text thepath) =
+ forever :
+ exitif tot < acc ;
+ seg := seg + 1 ;
+ tim := acc ;
+ acc := acc + subarclength (seg,seg+1) of thepath ;
+ endfor ;
+ (arcpoint (seg,tot-tim) of thepath)
+ enddef ;
+
+ vardef arcpoints_c(expr thepath, cnt) =
+ save len, aln, seg, tot, tim, stp, acc ;
+ numeric len ; len := length thepath ;
+ numeric aln ; aln := arclength thepath ;
+ numeric seg ; seg := 0 ;
+ numeric tot ; tot := 0 ;
+ numeric tim ; tim := 0 ;
+ numeric stp ; stp := aln / cnt;
+ numeric acc ; acc := subarclength (0,1) of thepath ;
+ %
+ point 0 of thepath
+ for tot = stp step stp until aln :
+ -- mfun_arc_point(tot)(thepath)
+ endfor if cycle thepath : -- cycle fi
+ enddef ;
+\stopMPdefinitions
+\stopbuffer
+
+\typebuffer[option=tex] \getbuffer
+
+This got applied in three test agitators
+
+\startbuffer
+\startMPdefinitions
+ vardef agitate_e_a(expr thepath, S, n, fn, t, ft) =
+ save R, nbpoints, noiselevel ;
+ path R ; nbpoints := n ; noiselevel := t ;
+ R := thepath ;
+ for s=1 upto S :
+ nbpoints := nbpoints * fn ;
+ noiselevel := noiselevel * ft ;
+ R := arcpoints_a(R, nbpoints) ; % original Mikael
+ R := for i=0 upto length R:
+ (point i of R)
+ randomized noiselevel
+ ..
+ endfor cycle ;
+ endfor ;
+ R
+ enddef ;
+
+ vardef agitate_e_b(expr thepath, S, n, fn, t, ft) =
+ save R, nbpoints, noiselevel ;
+ path R ; nbpoints := n ; noiselevel := t ;
+ R := thepath ;
+ for s=1 upto S :
+ nbpoints := nbpoints * fn ;
+ noiselevel := noiselevel * ft ;
+ R := arcpoints_b(R, nbpoints) ; % merged Mikael
+ R := for i=0 upto length R:
+ (point i of R)
+ randomized noiselevel
+ ..
+ endfor cycle ;
+ endfor ;
+ R
+ enddef ;
+
+ vardef agitate_e_c(expr thepath, S, n, fn, t, ft) =
+ save R, nbpoints, noiselevel ;
+ path R ; nbpoints := n ; noiselevel := t ;
+ R := thepath ;
+ for s=1 upto S :
+ nbpoints := nbpoints * fn ;
+ noiselevel := noiselevel * ft ;
+ R := arcpoints_c(R, nbpoints) ; % split Mikael
+ R := for i=0 upto length R:
+ (point i of R)
+ randomized noiselevel
+ ..
+ endfor cycle ;
+ endfor ;
+ R
+ enddef ;
+\stopMPdefinitions
+\stopbuffer
+
+\typebuffer[option=tex] \getbuffer
+
+The new engine primitive shortens these agitators:
+
+\startbuffer
+\startMPdefinitions
+ vardef agitate_e_d(expr thepath, S, n, fn, t, ft) =
+ save R, nbpoints, noiselevel ;
+ path R ; nbpoints := n ; noiselevel := t ;
+ R := thepath ;
+ for s=1 upto S :
+ nbpoints := nbpoints * fn ;
+ noiselevel := noiselevel * ft ;
+ R := arcpointlist nbpoints of R;
+ R := for i=0 upto length R:
+ (point i of R)
+ randomized noiselevel
+ ..
+ endfor cycle ;
+ endfor ;
+ R
+ enddef ;
+\stopMPdefinitions
+\stopbuffer
+
+\typebuffer[option=tex] \getbuffer
+
+So are we done? Did we get rid of all bottlenecks? The answer is no! We still
+loop over the list in order to randomize the points. For each point we start at
+the beginning of the list. Let's first rewrite the agitator a little:
+
+\startbuffer
+\startMPdefinitions
+ vardef agitate_f_a(expr pth, iterations, points, pointfactor, noise, noisefactor) =
+ save currentpath, currentpoints, currentnoise ; path currentpath ;
+ currentpath := pth ;
+ currentpoints := points ;
+ currentnoise := noise ;
+ for step = 1 upto iterations :
+ currentpath := arcpointlist currentpoints of currentpath ;
+ currentnoise := currentnoise * noisefactor ;
+ currentpoints := currentpoints * pointfactor ;
+ if currentnoise <> 0 :
+ currentpath :=
+ for i = 0 upto length currentpath:
+ (point i of currentpath) randomized currentnoise ..
+ endfor
+ cycle ;
+ fi
+ endfor ;
+ currentpath
+ enddef ;
+\stopMPdefinitions
+\stopbuffer
+
+\typebuffer[option=tex] \getbuffer
+
+One of the \LUAMETAFUN\ extensions is a fast path iterator. In the next variant
+the \type {inpath} macro sets up an iterator (regular loop) with the length as
+final value. In the process the given path gets passed to \LUA\ where we can
+access it as array. The \type {pointof} macro (again a \LUA\ call) injects a
+pair. You will be surprised that even with passing the path to \LUA\ and calling
+out to \LUA\ to inject the pair this is way faster than the built|-|in \type
+{point of}.
+
+\startbuffer
+\startMPdefinitions
+ vardef agitate_f_b(expr pth, iterations, points, pointfactor, noise, noisefactor) =
+ save currentpath, currentpoints, currentnoise ; path currentpath ;
+ currentpath := pth ;
+ currentpoints := points ;
+ currentnoise := noise ;
+ for step = 1 upto iterations :
+ currentnoise := currentnoise * noisefactor ;
+ currentpoints := currentpoints * pointfactor ;
+ currentpath := arcpointlist currentpoints of currentpath ;
+ if currentnoise <> 0 :
+ currentpath :=
+ for i inpath currentpath :
+ (pointof i) randomized currentnoise ..
+ endfor
+ cycle ;
+ fi
+ endfor ;
+ currentpath
+ enddef ;
+\stopMPdefinitions
+\stopbuffer
+
+\typebuffer[option=tex] \getbuffer
+
+It was tempting to see if a more native solution pays of. One problem there is
+that a path is not really suitable for that as we currently don't have a data
+type that represents a point. Okay, actually we sort of have because we can use
+the transform record that has six points but that is something I will look into
+later (it just got added to the todo list).
+
+The \typ {i within pth} iterator is no conceptual beauty but does the job. Just
+keep in mind that it is just means for this kind of applications: run over a path
+point by point. The \type {i} has the current point number. Because we run over a
+path following the links we only run forward.
+
+\startbuffer
+\startMPdefinitions
+ vardef agitate_f_c(expr pth, iterations, points, pointfactor, noise, noisefactor) =
+ save currentpath, currentpoints, currentnoise ; path currentpath ;
+ currentpath := pth ;
+ currentpoints := points ;
+ currentnoise := noise ;
+ for step = 1 upto iterations :
+ currentnoise := currentnoise * noisefactor ;
+ currentpoints := currentpoints * pointfactor ;
+ currentpath := arcpointlist currentpoints of currentpath ;
+ if currentnoise <> 0 :
+ currentpath :=
+ for i within currentpath :
+ pathpoint
+ randomized currentnoise
+ ..
+ endfor
+ cycle ;
+ fi
+ endfor ;
+ currentpath
+ enddef ;
+\stopMPdefinitions
+\stopbuffer
+
+\typebuffer[option=tex] \getbuffer
+
+Any primitive solution more complex than this, like first creating a fast access
+data structure, of having a double linked list, or using some iterator larger
+than a simple numeric is very likely to have no gain over the super fast \LUA\
+variant.
+
+\startMPdefinitions
+ vardef agitate_x(expr thepath, S, n, fn, t, ft) =
+ save R, nbpoints ;
+ path R ; nbpoints := n ;
+ R := thepath ;
+ for s=1 upto S :
+ nbpoints := nbpoints * fn ;
+ R := arcpointlist nbpoints of R ;
+ endfor ;
+ R
+ enddef ;
+\stopMPdefinitions
+
+\startMPdefinitions
+ def TestMe (expr method, col, justtest) =
+ path P ;
+
+ randomseed := 10;
+ % maxknotpool := 20000; % default is 1000
+ defaultscale := .05;
+
+ % NbCircles := 1 ; S := 1 ; nzero := 10 ; fn := 1.3 ; tzero := 5 ; ft := 0.8 ;
+ % NbCircles := 2 ; S := 10 ; nzero := 10 ; fn := 1.3 ; tzero := 5 ; ft := 0.8 ;
+ % NbCircles := 10 ; S := 5 ; nzero := 10 ; fn := 1.3 ; tzero := 5 ; ft := 0.8 ;
+ % NbCircles := 10 ; S := 10 ; nzero := 20 ; fn := 1.3 ; tzero := 5 ; ft := 0.8 ;
+ NbCircles := 15 ; S := 10 ; nzero := 10 ; fn := 1.3 ; tzero := 5 ; ft := 0.8 ;
+
+ for c = NbCircles downto 1 :
+ P := fullcircle scaled (c*6.5) scaled 3 ;
+ nzero := floor(arclength(P)*0.5);
+ if method == 0 : P := agitate_x (P, S, nzero, fn, tzero, ft) ;
+ elseif method == 1 : P := agitate_a (P, S, nzero, fn, tzero, ft) ;
+ elseif method == 2 : P := agitate_b (P, S, nzero, fn, tzero, ft) ;
+ elseif method == 3 : P := agitate_c (P, S, nzero, fn, tzero, ft) ;
+ elseif method == 4 : P := agitate_d (P, S, nzero, fn, tzero, ft) ;
+ elseif method == 51 : P := agitate_e_a(P, S, nzero, fn, tzero, ft) ;
+ elseif method == 52 : P := agitate_e_b(P, S, nzero, fn, tzero, ft) ;
+ elseif method == 53 : P := agitate_e_c(P, S, nzero, fn, tzero, ft) ;
+ elseif method == 54 : P := agitate_e_d(P, S, nzero, fn, tzero, ft) ;
+ elseif method == 61 : P := agitate_f_a(P, S, nzero, fn, tzero, ft) ;
+ elseif method == 62 : P := agitate_f_b(P, S, nzero, fn, tzero, ft) ;
+ elseif method == 63 : P := agitate_f_c(P, S, nzero, fn, tzero, ft) ;
+ else :
+ fi ;
+ if justtest :
+ % do nothing
+ elseif method == 0 :
+ draw textext("no draw") ;
+ else :
+ eofill P withcolor transparent(1,4/NbCircles,col) ;
+ draw P withpen pencircle scaled 0.1 transparent(1,4/NbCircles,.90[black,col]) ;
+ % drawpoints P withpen pencircle scaled 0.2 withcolor white ;
+ % drawpointlabels P withcolor white;
+ fi ;
+ endfor ;
+ enddef ;
+\stopMPdefinitions
+
+We show the average runtime for three runs. Here we don't render the paths, which
+takes about one second, including conversion to \PDF. Of course measurements like
+this can change a bit over time. To these times you need to add about a second
+for the draw and fill operations as well as conversion to a \PDF\ stream with
+transparencies. The improvement in runtime makes it possible to use agitators like
+this at runtime especially because normally one will not use such (combinations
+of) large paths.
+
+\starttabulate[|T|r|i2T|r|i2T|r|]
+ \BC agitate_a \NC 776.26 \BC agitate_e_a \NC 291.99 \BC agitate_f_a \NC 10.82 \NC \NR % 1 51 61
+ \BC agitate_b \NC 276.43 \BC agitate_e_b \NC 76.06 \BC agitate_f_b \NC 2.55 \NC \NR % 2 52 62
+ \BC agitate_c \NC 259.89 \BC agitate_e_c \NC 77.27 \BC agitate_f_c \NC 2.17 \NC \NR % 3 53 63
+ \BC agitate_d \NC 260.41 \BC agitate_e_d \NC 18.67 \BC \NC \NC \NR % 4 54
+\stoptabulate
+
+The final version of the agitator is slightly different because it depends if we
+start at zero or one but gives similar results and adapt the noise before or
+after the loop.
+
+\typebuffer[final:definition][option=tex]
+
+We use a similar example as in the mentioned article but coded a bit differently:
+
+\typebuffer[final:graphic][option=tex]
+
+For Mikael and me, who both like \METAPOST, it was a nice distraction from
+working months on extending math in \LUAMETATEX, but it also opens up the
+possibilities to do more with rendering (math) functions and graphics, so in the
+end we get paid back anyway.
+
+\stopchapter
+
+\stopcomponent
+
+% see agitate-002.tex
+
+% \startluacode
+% local t = {
+% 0, -- also initialization
+% 1, 2, 3, 4,
+% 51, 52, 53, 54,
+% 61, 62, 63,
+% }
+% for i=1,#t do
+% context.writestatus("TEST RUN",t[i])
+% context("\\testfeatureonce{3}{\\startMPcalculation TestMe (%i, blue, true) ; \\stopMPcalculation}",t[i])
+% end
+% \stopluacode
+
+% \testfeatureonce{1}{\startMPpage TestMe ( 0, \MPcolor{darkblue} , false) ; \stopMPpage}
+% \testfeatureonce{1}{\startMPpage TestMe ( 1, \MPcolor{darkblue} , false) ; \stopMPpage}
+% \testfeatureonce{1}{\startMPpage TestMe ( 2, \MPcolor{darkblue} , false) ; \stopMPpage}
+% \testfeatureonce{1}{\startMPpage TestMe ( 3, \MPcolor{darkred} , false) ; \stopMPpage}
+% \testfeatureonce{1}{\startMPpage TestMe ( 4, \MPcolor{darkgreen} , false) ; \stopMPpage}
+% \testfeatureonce{1}{\startMPpage TestMe (51, \MPcolor{darkred} , false) ; \stopMPpage}
+% \testfeatureonce{1}{\startMPpage TestMe (52, \MPcolor{darkgreen} , false) ; \stopMPpage}
+% \testfeatureonce{1}{\startMPpage TestMe (53, \MPcolor{darkblue} , false) ; \stopMPpage}
+% \testfeatureonce{1}{\startMPpage TestMe (54, \MPcolor{darkblue} , false) ; \stopMPpage}
+% \testfeatureonce{1}{\startMPpage TestMe (61, \MPcolor{darkyellow}, false) ; \stopMPpage}
+% \testfeatureonce{1}{\startMPpage TestMe (62, \MPcolor{darkyellow}, false) ; \stopMPpage}
+% \testfeatureonce{1}{\startMPpage TestMe (63, \MPcolor{darkyellow}, false) ; \stopMPpage}
+
+% \stoptext
diff --git a/doc/context/sources/general/manuals/ontarget/ontarget-ridofjit.tex b/doc/context/sources/general/manuals/ontarget/ontarget-ridofjit.tex
new file mode 100644
index 000000000..e26e9bb7e
--- /dev/null
+++ b/doc/context/sources/general/manuals/ontarget/ontarget-ridofjit.tex
@@ -0,0 +1,111 @@
+% language=us runpath=texruns:manuals/ontarget
+
+\startcomponent ontarget-dk
+
+\environment ontarget-style
+
+\startchapter[title={Getting rid of jit}]
+
+At the \NTG\ meeting there was a short discussion about performance of the
+\OPENTYPE\ font machinery. Currently we still support \LUAJITTEX\ and although
+the \MKIV\ code base is mostly separated from the \LMTX\ one there is still some
+compromise going on, as some \LUA\ code is shared and needs to adapt to the fact
+that \LUAJIT\ is stuck to \LUA 5.2 (sort of). One reason why we still support
+\LUAJITTEX\ is that there are users who like the performance gain. However, if
+these can switch to \CONTEXT\ we could get rid of \LUAJITTEX\ support. After all,
+\LUAJIT\ is stalled as is \FFI. Of course a plain \TEX\ users can object to using
+\CONTEXT\ but one can just use the basics and be as plain as possible.
+
+Performance of \LUAMETATEX\ is quite okay and it often performs better than
+\LUATEX\ or even \LUAJITTEX. One border case is for instance the somewhat
+overdone in terms of split feature steps is the Brill font. So, I decided to do
+some tests on my 2017 laptop that had replaced the 2013 one (Windows 10). We use
+cross compiled binaries. Here is the test:
+
+\starttyping
+% \enableexperiments[fonts.compact]
+
+\definefont[Fa][brill*default @ 10pt]
+\definefont[Fb][brill*default @ 12pt]
+\definefont[Fc][brill-bf*default @ 10pt]
+\definefont[Fd][brill-bf*default @ 12pt]
+
+\start \testfeatureonce{1000}{
+ \Fa \samplefile{tufte} \samplefile{tufte}\par
+}\stop \page \edef\TimeA{\elapsedtime}
+\start \testfeatureonce{1000}{
+ \Fa \samplefile{tufte}\par\Fb\samplefile{tufte}\par
+}\stop \page \edef\TimeB{\elapsedtime}
+\start \testfeatureonce{1000}{
+ \Fa \samplefile{tufte} \Fb\samplefile{tufte}\par
+}\stop \page \edef\TimeC{\elapsedtime}
+\start \testfeatureonce{1000}{
+ \Fa \samplefile{tufte} \Fd\samplefile{tufte}\par
+ \Fb \samplefile{tufte} \Fc\samplefile{tufte}\par
+}\stop \page \edef\TimeD{\elapsedtime}
+
+\startTEXpage[offset=10pt]
+ \strut\infofont
+ 2 par 1 font : \TimeA\par
+ 2 par 2 font : \TimeB\par
+ 1 par 2 font : \TimeC\par
+ 1 par 4 font : \TimeD\par
+\stopTEXpage
+\stoptyping
+
+The next table shows the best times from three tests where each one produces 1693
+pages in the default layout. We're talking of one run as normally \CONTEXT\ will
+run till a two pass stable state is reached (unless it is forced to one run),
+although in practice fixing a few typos will not for an extra run. Keep in mind
+that in \LUAMETATEX\ we have a \LUA\ driven backend that is more flexible with
+respect to fonts but therefore also adds some extra overhead. Also keep in mind
+that four different fonts per paragraph is a rare case.
+
+\starttabulate[|lT|c|c|c|c|]
+\NC
+ \BC 2 pars 1 font
+ \BC 2 pars 2 fonts
+ \BC 1 par 2 fonts
+ \BC 1 par 4 fonts
+\NC \NR
+\ML
+\BC luametatex \NC 8.9 \NC 9.4 \NC 12.1 \NC 24.6 \NC \NR
+\BC luametatex compact \NC 8.9 \NC 9.3 \NC 9.3 \NC 23.9 \NC \NR
+\BC luatex \NC 10.0 \NC 10.3 \NC 14.5 \NC 31.2 \NC \NR
+\BC luajittex \NC 8.0 \NC 8.1 \NC 11.4 \NC 23.2 \NC \NR
+\stoptabulate
+
+One should take these measurements with a grain of salt because it also depends
+on the system load, but it shows that there is no real need to favor a
+\LUAJITTEX\ setup over a \LUAMETATEX\ one. In the meantime the default \LUATEX\
+binaries exceed 7~MB (and the hb variant adds quite a bit more) which
+\LUAMETATEX\ stays around 3~MB which is nice for high performance setups with
+thousands of (small) runs.
+
+Just for the record, when we use Dejavu Serif we get 2767 pages and the following
+timings. Again, the differences between \LUAMETATEX\ and \LUAJITTEX\ is not that
+significant, especially when you realize that we're not doing anything fancy that
+more runtime. In practice fonts are only part of the story.
+
+\starttabulate[|lT|c|c|c|c|]
+\NC
+ \BC 2 pars 1 font
+ \BC 2 pars 2 fonts
+ \BC 1 par 2 fonts
+ \BC 1 par 4 fonts
+\NC \NR
+\ML
+\BC luametatex \NC 4.2 \NC 4.4 \NC 5.0 \NC 10.8 \NC \NR
+\BC luametatex compact \NC 4.2 \NC 4.5 \NC 4.5 \NC 10.5 \NC \NR
+\BC luatex \NC 4.9 \NC 5.0 \NC 6.2 \NC 13.3 \NC \NR
+\BC luajittex \NC 4.0 \NC 4.0 \NC 5.0 \NC 10.3 \NC \NR
+\stoptabulate
+
+% I tried to run \XETEX\ on the same file but that failed for some reason (it looks
+% like it got stuck in updating the font database; some 50~MB binaries are needed
+% so I guess I messed up somewhere).
+
+\stopchapter
+
+\stopcomponent
+
diff --git a/doc/context/sources/general/manuals/ontarget/ontarget.tex b/doc/context/sources/general/manuals/ontarget/ontarget.tex
index d6b7ad149..d17b09979 100644
--- a/doc/context/sources/general/manuals/ontarget/ontarget.tex
+++ b/doc/context/sources/general/manuals/ontarget/ontarget.tex
@@ -18,6 +18,12 @@
\component ontarget-dk
\component ontarget-anchoring
\component ontarget-math
+ \component ontarget-binary
+ \component ontarget-metapost
+ \component ontarget-makesnosense
+ \component ontarget-makessense
+ \component ontarget-alsomath
+ \component ontarget-ridofjit
\stopbodymatter
\stopdocument