From f72c2cf29d36ae836c894bad29dfd965d1af0236 Mon Sep 17 00:00:00 2001
From: Hans Hagen <pragma@wxs.nl>
Date: Sun, 18 Aug 2019 22:51:53 +0200
Subject: 2019-08-18 22:26:00

---
 .../manuals/followingup/followingup-directions.tex | 778 +++++++++++++++++++++
 1 file changed, 778 insertions(+)
 create mode 100644 doc/context/sources/general/manuals/followingup/followingup-directions.tex

(limited to 'doc/context/sources/general/manuals/followingup/followingup-directions.tex')

diff --git a/doc/context/sources/general/manuals/followingup/followingup-directions.tex b/doc/context/sources/general/manuals/followingup/followingup-directions.tex
new file mode 100644
index 000000000..244baff90
--- /dev/null
+++ b/doc/context/sources/general/manuals/followingup/followingup-directions.tex
@@ -0,0 +1,778 @@
+% language=us
+
+\startcomponent followingup-directions
+
+\environment followingup-style
+
+\startchapter[title={Directions}]
+
+\startsection[title={Introduction}]
+
+In \LUATEX\ the directional model taken from \OMEGA\ has been upgraded a bit. For
+instance in addition to the \type {\*dir} commands we have \type {\*direction}
+commands that take a number instead of a keyword. This is a bit more efficient and
+consistent as using these keywords was kind of un|-|\TEX. Internally direction
+related nodes (text directions) are not whatsits but first class nodes. We also
+use a subtype that indicates the push or pop state.
+
+The \LUATEX\ directional model provides four directions which is a subset of the
+many that \OMEGA\ provided, indicated by three letters, like \type {TRT} and
+\type {LTT}. In the beginning we had them all fixed\footnote {This was doen by
+Hartmut by rigorously checking all possible combinations} and thereby implemented
+but being in doubt about their usefulness we dropped most of them, just four were
+kept. However, in practice only right|-|to|-|left makes sense. Going from top to
+bottom in Japanese or Mongolian can also involve glyph rotation, which actually
+is not implemented in the engine at all. Spacing and inter|-|character breaks
+have to be implemented and in the end one has to combine the results into a
+page body. So, in practice you end up with juggling node list and macro magic in
+the page builder. The \type {LTL} (number~2) and \type {RTT} (number~3)
+directions are not used for serious work. Therefore, in \LUAMETATEX\ the model
+has been adapted. In the end, it was not entirely clear anyway what the three
+letters were indicating in each direction property (page, body, par, text, math)
+as most had no real meaning.
+
+As a side note: if you leave the (not really working well) vertical directions
+out of the picture, directional typesetting is not that hard to deal with and has
+hardly any consequences for the code. This is because horizontal dimensions are
+not affected by direction, only the final ship out is: when a run (wrapped in an
+hbox) goes the other way, the backend effectively has to skip the width and then
+with each component goes back. Not much more is involved. This means that a
+bidirectional engine is rather simple. The complications are more in the way a
+macro package deals with it, in relation to the input as well as the layout. The
+backend has to do the real work. \footnote {Of course when one hooks in \LUA\
+code taking care of direction can be needed!}
+
+\stopsection
+
+\startsection[title=Two directions]
+
+We now have only two directions left: the default left|-|to|-|right (l2r) and
+right|-|to|-|left (r2l). They work the same as before and in the backend we can
+get rid of the fuzzy parallel and rotation (which actually was just stacking
+nodes) heuristics.
+
+Reducing the lot to two directions simplifies some code in the engine. This is
+because when calculating dimensions a change in horizontal direction doesn't
+influence the width, height and depth in an orthogonal way. Because there are no
+longer top|-|down items we don't need to swap the height and or depth with the
+width. This also means that we don't need to keep much track of direction
+changes. Technically an hpack doesn't need to know its own direction and we can
+set it to any value afterwards if we want because the calculation are not
+influenced by it; so that also simplified matters.
+
+The \type {\bodydir} and \type {\pagedir} already didn't make much sense, and in
+\CONTEXT\ we actually intercepted them, so now they are removed. The body
+direction is always left|-|to|-|right and the page direction was only consulted
+in the backend code which we no longer have. Another side effect of going with
+only two directions is that rules no longer need to carry the direction property:
+there is no flipping of width with height and depth needed.
+
+\stopsection
+
+\startsection[title=Four orientations]
+
+Instead of the top|-|bottom variants we now have four orientations plus a bunch
+of anchoring options. Of course one could use the backend save, restore and
+matrix whatsits but a natural feature makes more sense. Let's start with what
+happens normally:
+
+\startbuffer[1]
+This is a \LUAMETATEX\ goodie.
+\stopbuffer
+
+\startbuffer[2]
+\hbox orientation 2{This is a \LUAMETATEX\ goodie.}
+\stopbuffer
+
+\startbuffer[3]
+This is a \hbox orientation 2{\LUAMETATEX} goodie.
+\stopbuffer
+
+\startbuffer[4]
+\hbox orientation 2{This is a \hbox orientation 002{\LUAMETATEX} goodie.}
+\stopbuffer
+
+\blank{\showstruts\strut}\quad\ruledhbox{\inlinebuffer[1]}\quad{\showstruts\strut}\blank
+
+This line has height and depth. We can rotate this sentence by 180 degrees around
+the baseline in which case the depth and height are flipped.
+
+\blank{\showstruts\strut}\quad\ruledhbox{\inlinebuffer[2]}\quad{\showstruts\strut}\blank
+
+or we flip part:
+
+\blank{\showstruts\strut}\quad\ruledhbox{\inlinebuffer[3]}\quad{\showstruts\strut}\blank
+
+or flip nested:
+
+\blank{\showstruts\strut}\quad\ruledhbox{\inlinebuffer[4]}\quad{\showstruts\strut}\blank
+
+but we're talking boxes, so the above examples are defined as:
+
+\typebuffer[1,2,3,4]
+
+The \type {orientation} keyword does the magic here. There are four such
+orientations with zero being the default. We saw that two rotates over 180
+degrees, so one and three are left for up and down.
+
+\startbuffer[5]
+\hbox orientation 0 {\TEX} and
+\hbox orientation 1 {\TEX} and
+\hbox orientation 2 {\TEX} and
+\hbox orientation 3 {\TEX}
+\stopbuffer
+
+\blank{\showstruts\strut}\quad\ruledhbox{\inlinebuffer[5]}\quad{\showstruts\strut}\blank
+
+This is codes as:
+
+\typebuffer[5]
+
+The landscape and seascape variants both sit on top of the baseline while the
+flipped variant has its depth swapped with the height. Although this would be
+enough a bit more control is possible. The number is actually a three byte hex
+number:
+
+\starttyping
+0x<X><Y><O>
+\stoptyping
+
+or in \TEX\ syntax
+
+\starttyping
+"<X><Y><O>
+\stoptyping
+
+We saw that the last byte regulates the orientation. The first and second one
+deal with anchoring horizontally and vertically. The vertical options of the
+horizontal variants anchor on the baseline, lower corner, upper corner or center.
+
+\startbuffer[6]
+\hbox orientation "002 {\TEX} and
+\hbox orientation "012 {\TEX} and
+\hbox orientation "022 {\TEX} and
+\hbox orientation "032 {\TEX}
+\stopbuffer
+
+\typebuffer[6]
+
+\blank{\showstruts\strut}\quad\ruledhbox{\inlinebuffer[6]}\quad{\showstruts\strut}\blank
+
+\startbuffer[7]
+\hbox orientation "002 {\TEX} and
+\hbox orientation "102 {\TEX} and
+\hbox orientation "202 {\TEX} and
+\hbox orientation "302 {\TEX} and
+\hbox orientation "402 {\TEX}
+\stopbuffer
+
+The horizontal options of the horizontal variants anchor in the center, left, right,
+halfway left and halfway right.
+
+\typebuffer[7]
+
+\blank{\showstruts\strut}\quad\ruledhbox{\inlinebuffer[7]}\quad{\showstruts\strut}\blank
+
+All combinations will be shown on the next pages, so we suffice with telling that
+for the vertical variants we can vertically anchor on the baseline, top, bottom
+or center, while horizontally we center, hang left or right, halfway left or
+right, and in addition align on the (rotated) baseline left or right.
+
+The orientation has consequences for the dimensions so they are dealt with in the
+expected way in constructing lines, paragraphs and pages, but the anchoring is
+virtual. As a bonus, we have two extra variants for orientation zero: on top of
+baseline or below, with dimensions taken into account.
+
+\startbuffer[8]
+\hbox orientation "000 {\TEX} and
+\hbox orientation "004 {\TEX} and
+\hbox orientation "005 {\TEX}
+\stopbuffer
+
+\typebuffer[8]
+
+\blank{\showstruts\strut}\quad\ruledhbox{\inlinebuffer[8]}\quad{\showstruts\strut}\blank
+
+\definecolor[brcolorh][r=1,t=.5,a=1]
+\definecolor[brcolord][b=1,t=.5,a=1]
+\definecolor[brcolorm][g=1,t=.5,a=1]
+
+\starttexdefinition ShowAnchor
+    \blackrule[width=2pt,height=1pt,depth=1pt,color=darkgray]
+\stoptexdefinition
+
+\starttexdefinition DemoRule#1#2#3
+    \ShowAnchor
+    \ruledhbox {
+        \hbox orientation "#1#2#3 {
+            \blackrule[height=6mm,depth=0mm,width=8mm,color=brcolorh]\kern-8mm\relax
+            \blackrule[height=0mm,depth=3mm,width=8mm,color=brcolord]\kern-8mm\relax
+            \blackrule[height=2mm,depth=-1mm,width=8mm,color=brcolorm]
+        }
+    }
+    \ShowAnchor
+\stoptexdefinition
+
+\starttexdefinition DemoText#1#2#3
+    \ShowAnchor
+    \ruledhbox{\hbox orientation "#1#2#3 {\red\TEX}}
+    \ShowAnchor
+\stoptexdefinition
+
+\starttexdefinition DemoSet #1#2
+    \startcombination[nx=4,ny=7,width=10cm]
+        {#200#1}{\ttxx 0x00#1} {#201#1}{\ttxx 0x01#1} {#202#1}{\ttxx 0x02#1} {#203#1}{\ttxx 0x03#1}
+        {#210#1}{\ttxx 0x10#1} {#211#1}{\ttxx 0x11#1} {#212#1}{\ttxx 0x12#1} {#213#1}{\ttxx 0x13#1}
+        {#220#1}{\ttxx 0x20#1} {#221#1}{\ttxx 0x21#1} {#222#1}{\ttxx 0x22#1} {#223#1}{\ttxx 0x23#1}
+        {#230#1}{\ttxx 0x30#1} {#231#1}{\ttxx 0x31#1} {#232#1}{\ttxx 0x32#1} {#233#1}{\ttxx 0x33#1}
+        {#240#1}{\ttxx 0x40#1} {#241#1}{\ttxx 0x41#1} {#242#1}{\ttxx 0x42#1} {#243#1}{\ttxx 0x43#1}
+        {#250#1}{\ttxx 0x50#1} {#251#1}{\ttxx 0x51#1} {#252#1}{\ttxx 0x52#1} {#253#1}{\ttxx 0x53#1}
+        {#260#1}{\ttxx 0x60#1} {#261#1}{\ttxx 0x61#1} {#262#1}{\ttxx 0x62#1} {#263#1}{\ttxx 0x63#1}
+    \stopcombination
+\stoptexdefinition
+
+\startplacefigure[title={orientation 0}]\scale[width=\textwidth]{\framed[offset=1cm]{\DemoSet0\DemoRule}}\stopplacefigure
+\startplacefigure[title={orientation 1}]\scale[width=\textwidth]{\framed[offset=1cm]{\DemoSet1\DemoRule}}\stopplacefigure
+\startplacefigure[title={orientation 2}]\scale[width=\textwidth]{\framed[offset=1cm]{\DemoSet2\DemoRule}}\stopplacefigure
+\startplacefigure[title={orientation 3}]\scale[width=\textwidth]{\framed[offset=1cm]{\DemoSet3\DemoRule}}\stopplacefigure
+
+\startplacefigure[title={orientation 0}]\scale[width=\textwidth]{\framed[offset=1cm]{\DemoSet0\DemoText}}\stopplacefigure
+\startplacefigure[title={orientation 1}]\scale[width=\textwidth]{\framed[offset=1cm]{\DemoSet1\DemoText}}\stopplacefigure
+\startplacefigure[title={orientation 2}]\scale[width=\textwidth]{\framed[offset=1cm]{\DemoSet2\DemoText}}\stopplacefigure
+\startplacefigure[title={orientation 3}]\scale[width=\textwidth]{\framed[offset=1cm]{\DemoSet3\DemoText}}\stopplacefigure
+
+% \page
+
+The anchoring can look somewhat confusing but you need to keep in mind that it is
+normally only used in very controlled circumstances and not in running text.
+Wrapped in macros users don't see the details. We're talking boxes here, so or
+instance:
+
+\startbuffer
+test\quad
+\hbox orientation 3 \bgroup
+    \strut test\hbox orientation "002 \bgroup\strut test\egroup test%
+\egroup \quad
+\hbox orientation 3 \bgroup
+    \strut test\hbox orientation "002 \bgroup\strut test\egroup test%
+\egroup \quad
+\hbox orientation 3 \bgroup
+    \strut test\hbox orientation "012 \bgroup\strut test\egroup test%
+\egroup \quad
+\hbox orientation 3 \bgroup
+    \strut test\hbox orientation "022 \bgroup\strut test\egroup test%
+\egroup \quad
+\hbox orientation 3 \bgroup
+    \strut test\hbox orientation "032 \bgroup\strut test\egroup test%
+\egroup \quad
+\hbox orientation 3 \bgroup
+    \strut test\hbox orientation "042 \bgroup\strut test\egroup test%
+\egroup
+\quad test
+\stopbuffer
+
+\typebuffer
+
+gives:
+
+\startlinecorrection[blank]
+\ruledhbox\bgroup \showcolorstruts \showboxes \inlinebuffer \egroup
+\stoplinecorrection
+
+\stopsection
+
+\startsection[title={Right|-|to|-|left typesetting}]
+
+Another aspect to keep in mind when we transform is the already mentioned
+right|-|to|-|left direction. We show some examples where we do things like this:
+
+\starttyping
+\hbox{\hbox
+    orientation #1
+    {\strut abcd}}
+\hbox{\hbox
+    orientation #1
+    to 15mm
+    {\strut abcd}}
+\hbox{\hbox
+    orientation #1
+    direction 1
+    {\righttoleft\strut abcd}}
+\hbox{\hbox
+    orientation #1
+    direction 1
+    to 15mm {\righttoleft\strut abcd}}
+\stoptyping
+
+\starttexdefinition TestH #1
+    \dontcomplain
+    \setbox\scratchbox\hbox{abcd}%
+    x\ruledhbox{\hbox orientation #1             to \wd\scratchbox  {\strut abcd}}x\quad
+    x\ruledhbox{\hbox orientation #1             to 15mm            {\strut abcd}}x\quad
+    x\ruledhbox{\hbox orientation #1 direction 1 to \wd\scratchbox  {\righttoleft\strut abcd}}x\quad
+    x\ruledhbox{\hbox orientation #1 direction 1 to 15mm            {\righttoleft\strut abcd}}x%
+\stoptexdefinition
+
+\starttexdefinition TestV #1
+    \dontcomplain
+    \setbox\scratchbox\hbox{abcd}%
+    x\ruledvbox{\vbox orientation #1             {\hsize \wd\scratchbox\strut abcd}}x\quad
+    x\ruledvbox{\vbox orientation #1             {\hsize           15mm\strut abcd}}x\quad
+    x\ruledvbox{\vbox orientation #1 {\righttoleft\hsize \wd\scratchbox\strut abcd}}x\quad
+    x\ruledvbox{\vbox orientation #1 {\righttoleft\hsize           15mm\strut abcd}}x%
+\stoptexdefinition
+
+\startplacefigure[title={Horizontal boxes.}]
+    \startcombination[nx=2,ny=2]
+        {\TestH 0} {orientation 0}
+        {\TestH 2} {orientation 2}
+        {\TestH 1} {orientation 1}
+        {\TestH 3} {orientation 3}
+    \stopcombination
+\stopplacefigure
+
+\startplacefigure[title={Vertical boxes.}]
+    \startcombination[nx=2,ny=2]
+        {\TestV 0} {orientation 0}
+        {\TestV 2} {orientation 2}
+        {\TestV 1} {orientation 1}
+        {\TestV 3} {orientation 3}
+    \stopcombination
+\stopplacefigure
+
+\stopsection
+
+\startsection[title={Vertical typesetting}]
+
+I'm no expert on vertical typesetting and have no application for it either. But
+from what I've seen vertically positioned glyphs are normally used in rather
+straightforward situations. Here I will just give some examples of how
+transformations can be used to achieve certain effects. It is no big deal to make
+macros or use \LUA\ to apply magic to node lists but it is beyond this description
+to discuss that.
+
+Before we fine tune this example we have to discuss another feature. When a \typ
+{orientation} keyword is given optionally \type {xoffset} and \type {yoffset} can
+be specified. These offsets are {\em not} taken into account when calculating
+dimensions. This is different from the offsets (at the \LUA\ end) used in glyphs
+because there the vertical offset is taken into account. Here are some examples
+of offsets in packaged lists:
+
+\startbuffer
+\hbox
+    {test 1}
+\hbox
+    orientation 0
+    yoffset  15pt
+    xoffset 150pt
+    {test}
+\vbox
+    orientation 0
+    {\hbox{test}}
+\vbox
+    orientation 0
+    yoffset  -5pt
+    xoffset 130pt
+    {\hbox{test}}
+\vbox
+    orientation 0
+    yoffset 2pt
+    {\hbox{test}}
+\stopbuffer
+
+\typebuffer
+
+\startlinecorrection[blank]
+    \start \showboxes \bfd \getbuffer \stop
+\stoplinecorrection
+
+In order to demonstrate some hacking, we first define a font that supports
+chinese glyphs:
+
+\startbuffer
+\definefont[NotoCJK][NotoSansCJKtc-Regular*default @ 24pt]
+\stopbuffer
+
+\typebuffer \getbuffer
+
+We put some text in a horizontal box; it doesn't show up in verbatim but you
+get the idea nevertheless:
+
+\startbuffer
+\hbox{\NotoCJK 通用规范汉字表}
+\stopbuffer
+
+\typebuffer
+
+\startlinecorrection[blank]
+    \start \showboxes \getbuffer \stop
+\stoplinecorrection
+
+Let's now rotate this line of text:
+
+\startbuffer[1]
+\hbox orientation 1 {\NotoCJK 通用规范汉字表}
+\stopbuffer
+
+\typebuffer[1]
+
+The result is shown in a while. Because we also need to rotate the glyphs we
+deconstruct the box.
+
+\startbuffer[2]
+\hbox orientation 1 \bgroup \NotoCJK %
+    \vbox {\hbox {通}}%
+    \vbox {\hbox {用}}%
+    \vbox {\hbox {规}}%
+    \vbox {\hbox {test}}%
+    \vbox {\hbox {范}}%
+    \vbox {\hbox {汉}}%
+    \vbox {\hbox {字}}%
+    \vbox {\hbox {表}}%
+\egroup
+\stopbuffer
+
+\typebuffer[2]
+
+Next we rotate the glyphs.
+
+\startbuffer[3]
+\hbox orientation 1 \bgroup \NotoCJK %
+    \vbox orientation 3 {\hbox {通}}%
+    \vbox orientation 3 {\hbox {用}}%
+    \vbox orientation 3 {\hbox {规}}%
+    \vbox orientation 0 {\hbox {test}}%
+    \vbox orientation 3 {\hbox {范}}%
+    \vbox orientation 3 {\hbox {汉}}%
+    \vbox orientation 3 {\hbox {字}}%
+    \vbox orientation 3 {\hbox {表}}%
+\egroup
+\stopbuffer
+
+\typebuffer[3]
+
+This still looks bad so we kick in some offsets and glue:
+
+\startbuffer[4]
+\dontleavehmode\hbox orientation 1 \bgroup \NotoCJK
+    \vbox
+        orientation 0 yoffset -.1ex
+        {\hbox orientation 3 {通}}\hskip.2ex
+    \vbox
+        orientation 0 yoffset -.1ex
+        {\hbox orientation 3 {用}}\hskip.2ex
+    \vbox
+        orientation 0 yoffset -.1ex
+        {\hbox orientation 3 {规}}\hskip.6ex
+    \vbox
+        {\hbox             {test}}\hskip.2ex
+    \vbox
+        orientation 0 yoffset -.1ex
+        {\hbox orientation 3 {范}}\hskip.2ex
+    \vbox
+        orientation 0 yoffset -.1ex
+        {\hbox orientation 3 {汉}}\hskip.2ex
+    \vbox
+        orientation 0 yoffset -.1ex
+        {\hbox orientation 3 {字}}\hskip.2ex
+    \vbox
+        orientation 0 yoffset -.1ex
+        {\hbox orientation 3 {表}}\hskip.2ex
+\egroup
+\stopbuffer
+
+\typebuffer[4]
+
+Now we're ready to compare the results
+
+\startlinecorrection[blank]
+    \startcombination[9*1]
+        {\showboxes \getbuffer[1]} {1}
+        {\showboxes \getbuffer[2]} {2}
+        {\showboxes \getbuffer[3]} {3}
+        {\showboxes \getbuffer[4]} {4}
+        {\quad}{}
+        {\getbuffer[1]} {1}
+        {\getbuffer[2]} {2}
+        {\getbuffer[3]} {3}
+        {\getbuffer[4]} {4}
+    \stopcombination
+\stoplinecorrection
+
+This could of course also be done with traditional kerns, raising and|/|or
+lowering and messing around with dimensions. It's just that when manipulating
+such rather complex constructs a little help (and efficiency) makes a difference,
+also at the \LUA\ end. Of course one can argue the result but all is
+programmable in the end.
+
+\stopsection
+
+\startsection[title={Considerations}]
+
+Just in case you wonder if using these offsets is better than using normal kerning
+and shifting, in practice offsets are not more efficient. Let's compare the
+alternatives. We go from most to least efficient.
+
+\starttyping
+\setbox\scratchbox\hpack{}
+\boxxoffset\scratchbox\scratchdimen
+\boxyoffset\scratchbox\scratchdimen
+\stoptyping
+
+This sets the offsets and by setting them we also trigger the transform. Scanning
+is fast and so is setting them. One million times expanding this takes (as
+reference) 0.73 seconds on my current machine.
+
+\starttyping
+\setbox\scratchbox\hpack
+  orientation \zerocount
+  xoffset     \scratchdimen
+  yoffset     \scratchdimen
+  {}
+\stoptyping
+
+This takes a bit more time, 1.11 seconds, because the keywords have to be scanned
+which happens on a token by token base.
+
+\starttyping
+\setbox\scratchbox\hpack{}
+\scratchheight\ht\scratchbox
+\scratchdepth\dp\scratchbox
+\setbox\scratchbox\hpack
+  {\kern\scratchdimen
+   \raise\scratchdimen\box\scratchbox
+   \kern\scratchdimen}
+\ht\scratchbox\scratchheight
+\dp\scratchbox\scratchdepth
+\stoptyping
+
+Now we're up to 1.69 seconds for the million expansions. Not only do we have some
+parsing going on, but we also have assignments and extra packing, which means
+calculations taking place.
+
+\starttyping
+\setbox\scratchbox\hpack{}
+\scratchwidth\wd\scratchbox
+\scratchheight\ht\scratchbox
+\scratchdepth\dp\scratchbox
+\setbox\scratchbox\hpack
+  {\kern\scratchdimen
+   \raise\scratchdimen\box\scratchbox}
+\wd\scratchbox\scratchwidth
+\ht\scratchbox\scratchheight
+\dp\scratchbox\scratchdepth
+\stoptyping
+
+This variant is about as fast, as I measured 1.72 seconds. So, compared to the
+0.73 seconds for the first variant, is this better? Does it help when we look at
+our existing macros and adapt them?
+
+Normally we don't have an empty box and normally we use \type {\hbox} because we
+want the content to be processed. And a million times building a list and
+processing content (which means runs over the list) will make the differences
+in timing become noise. Add to that garbage collection (in \LUA) and memory
+management (in \TEX) and it even becomes unpredictable. Seeing differences of
+a factor two in such timings is no exception.
+
+Another aspect is the parsing. When these commands are wrapped in macros we're
+talking expanding tokens which is pretty fast. When it comes from the input file
+a conversion to tokens has to happen too. And we will never see millions of such
+sequences in a source file.
+
+The backend also plays a role. Handling a kern or shift is more efficient than
+analyzing transforms (and offsets) especially in a \LUA\ variant. But on the
+other hand, we don't have an extra wrapping in a box so that actually saves work.
+
+So, before a \CONTEXT\ user thinks \quotation {Let's update macros and change
+policy.}, just consider staying with proven good old \TEX\ approaches. These
+features are mostly meant for efficient low level manipulations as discussed in
+relation to for instance handling scripts. In the rather large \CONTEXT\ code
+base there are really only a few places where it will make code look nicer, but
+there I don't expect an impact on performance.
+
+\stopsection
+
+\startsection[title={Integration}]
+
+How these mechanisms are used depends on ones needs and the macro package used.
+It makes no sense to cook up generic solutions because integration in a macro
+package is too different. But anyhow we'll give an example of some (definitely
+non optimized) \LUA\ magic.
+
+\startbuffer
+\startluacode
+local glyph_id = node.id("glyph")
+local fontdata = fonts.hashes.identifiers -- assumes generic font loader
+
+local function is_vertical(c)
+  -- more ranges matter but this will do here
+  return c >= 0x04E00 and c <= 0x09FFF
+end
+
+function document.go_vertical(boxnumber)
+  local box = tex.getbox(boxnumber)
+  local n   = box.list
+  while n do
+    if n.id == glyph_id and is_vertical(n.char) then
+      local o = .2 * fontdata[n.font].parameters.xheight
+      local prev, next = n.prev, n.next
+      n.next, n.prev = nil, nil
+      local l = nodes.new("hlist")
+      l.list = n
+      local w, h, d = n.width, n.height, n.depth
+      if prev then
+          prev.next, l.prev = l, prev
+      else
+          box.list = l
+      end
+      if next then
+          l.next, next.prev = next, l
+      end
+      l.width, l.height, l.depth  = h + d + o, w, 0
+      l.orientation = 0x003
+      l.xoffset, l.yoffset = o/2, -o/2
+      l.hoffset, l.doffset = h, d - o
+      n = next
+    else
+      n = n.next
+    end
+  end
+end
+\stopluacode
+\stopbuffer
+
+\typebuffer \getbuffer
+
+We will use some other magic that we won't discuss here which relates to handling
+scripts. For Hangul one needs to inject breakpoints and if needed also glue
+between characters. The script environment does this. We also need to bump the
+interline spacing. First we define a regular text helper and an auxiliary box.
+
+\startbuffer[1]
+\unexpanded\def\stripe#1%
+  {\hbox orientation 0 yoffset .2\exheight{\strut #1}}
+
+\newbox\MyVerticalBox
+\stopbuffer
+
+\typebuffer[1]
+
+Next we fill that box with some mix of text (I have no clue what, as I just
+copied it from some web page).
+
+\startbuffer[2a]
+\setbox\MyVerticalBox\hbox \bgroup
+    \NotoCJK
+    \startscript[hangul]%
+    \dorecurse{20}{通用规范汉字表 \stripe{test #1} }%
+    \unskip % remove last space
+    \stopscript
+\egroup
+\stopbuffer
+
+\typebuffer[2a]
+
+We then apply the \LUA\ magic to the result:
+
+\startbuffer[3a]
+\ctxlua{document.go_vertical(\number\MyVerticalBox)}
+\stopbuffer
+
+\typebuffer[3a]
+
+and finally assemble the result:
+
+\startbuffer[4a]
+\ruledvbox orientation 1 to \textwidth \bgroup
+    \setupinterlinespace[40pt]
+    \hsize .95\textheight
+    \unhbox\MyVerticalBox
+    \vfill
+\egroup
+\stopbuffer
+
+\typebuffer[4a]
+
+The result is shown in \in {figure} [fig:verticalmagic-1]. Of course this
+approach is not that user friendly but it just serves as example. In \CONTEXT\ we
+can follow a different route. First we define a new font feature. It is probably
+clear that we need some code elsewhere that does something useful with this
+information, but I will nos show this as it is rather \CONTEXT\ dependent.
+
+\startbuffer[2b]
+\definefontfeature
+  [vertical]
+  [vertical={%
+    orientation=3,%
+    down=.1,%
+    right=.1,%
+    ranges={%
+      cjkcompatibility,%
+      cjkcompatibilityforms,%
+      cjkcompatibilityideographs,%
+      cjkcompatibilityideographssupplement,%
+      cjkradicalssupplement,%
+    % cjkstrokes,%
+      cjksymbolsandpunctuation,%
+      cjkunifiedideographs,%
+      cjkunifiedideographsextensiona,%
+      cjkunifiedideographsextensionb,%
+      cjkunifiedideographsextensionc,%
+      cjkunifiedideographsextensiond,%
+      cjkunifiedideographsextensione,%
+      cjkunifiedideographsextensionf,%
+    }%
+  }]
+\stopbuffer
+
+\typebuffer[2b]
+
+We apply this feature to a font:
+
+\startbuffer[3b]
+\definefont
+  [NotoCJKvertical]
+  [NotoSansCJKtc-Regular*default,vertical @ 24pt]
+\stopbuffer
+
+\typebuffer[3b]
+
+\startbuffer[4b]
+\setbox\MyVerticalBox\hbox\bgroup
+    \NotoCJKvertical
+    \startscript[hangul]%
+    \dorecurse{20}{通用规范汉字表 \stripe{test #1} }%
+    \unskip
+    \stopscript
+\egroup
+\stopbuffer
+
+\typebuffer[4b]
+
+\startbuffer[5b]
+\ruledvbox orientation 1 to \textwidth \bgroup
+    \setupinterlinespace[40pt]
+    \hsize .95\textheight
+    \unhbox\MyVerticalBox
+    \vfill
+\egroup
+\stopbuffer
+
+\typebuffer[5b]
+
+The result is shown in \in {figure} [fig:verticalmagic-2]. Again this approach is
+not that user friendly but it already is a bit easier.
+
+\startplacefigure[reference=fig:verticalmagic-1,title={Some vertical magic using manipulations.}]
+    \getbuffer[1,2a,3a,4a]
+\stopplacefigure
+
+\startplacefigure[reference=fig:verticalmagic-2,title={Some vertical magic using fonts.}]
+    \getbuffer[1,2b,3b,4b,5b]
+\stopplacefigure
+
+\stopsection
+
+\stopchapter
+
+\stopcomponent
-- 
cgit v1.2.3

