ontarget-anchoring.tex /size: 10 Kb    last modification: 2024-01-16 10:21
1% language=us runpath=texruns:manuals/ontarget
2
3\startcomponent ontarget-eventually
4
5\environment ontarget-style
6
7\startchapter[title={Anchoring}]
8
9\startsection[title=Introduction]
10
11It is valid to question what functionality should be in the engine and what can
12best be implemented using callbacks and postprocessing of lists (and boxes)
13relying for instance on attributes as signals. In \LUATEX\ we are rather strict
14in this and assume that the second method is used. In \LUAMETATEX\ we still
15promote this but at the same time some (lightweight) functionality has been added
16to the engine that helps implementing some features more efficiently. Reasons are
17that it can be handy to carry (fundamental) properties around that are bound to
18nodes and that we can set them using primitives, especially for glyphs and boxes.
19That way they become part of the formal functionality that one can argue should
20be present in a modern engine. Examples for glyph nodes are scales, offsets and
21hyphenation, detailed ligature and kerning control. For box nodes we have for
22instance offsets and orientation. Most of these are always taken into account by
23core mechanisms like breaking paragraphs into lines, where dimensions matter in
24which case it really makes sense for them to be part of the engine design.
25
26Some properties are just passed on to for instance a font handler or the backend
27but still they belong to the core functionality. An example of the later is a
28(new) simple mechanism for anchoring boxes. This is not really a fundamental
29feature, because one can just move content around using a combination of kerning
30and boxing, either or not with offsets. But because we already have features like
31offsets to boxes it was not that much work to add anchoring as a more fundamental
32property. The frontend is agnostic to this feature because dimensions are kind of
33virtual here: the backend however carries the real burden. Because backends are
34written in \LUA\ it might have a performance hit simply because at least we need
35to check if this feature is used. Normally that can compensated when this feature
36{\em is} used because less work and shuffling around happens in the frontend. And
37when this feature is no longer experimental (and stays) we can gain some back by
38using it in existing scenarios. It sounds worse than it is because for
39orientations we already have to do some usage checking and we can share that
40check; in most situations nothing needs to be done anyway.
41
42\stopsection
43
44\startsection[title=The low level approach]
45
46When we anchor, a box can be a source and|/|or a target. Both are represented by
47a number and can be assigned via a keyword. These numbers can be picked up by the
48backend. Here is an example:
49
50\startbuffer
51\def\TestMe#1{%
52    \setbox \scratchbox \ruledvbox
53        source 123
54        orientation #1
55        \bgroup
56            \hsize7cm
57            \samplefile{zapf}
58            \hbox to 0pt
59                source 124 target 123
60                xoffset 20pt yoffset -30pt
61                {\darkred \bfc TEST1}%
62            \hbox to 0pt
63                source 125 target 124
64                xoffset 10pt yoffset -20pt
65                {\darkblue \bfc TEST2}%
66        \egroup
67    \box \scratchbox
68}
69\stopbuffer
70
71\typebuffer \getbuffer
72
73This example also uses a few offsets. The \quote {origin} is at the left edge of
74the baseline. Now, we could have passed the source and target as attribute and
75intercepting an attribute in the backend can work pretty well. However, the code
76that deals with the final result of the typesetting and thereby flushes it to for
77instance a \PDF\ file is, at least that is the setup we use in \CONTEXT,
78attribute agnostic. Mixing in attributes at that stage, except for user nodes and
79whatsits that are effectively plugins, is counter intuitive and all is already
80pretty complex so a clear separation of functionality makes a lot of sense. Of
81course the \CONTEXT\ approach is not the only one when it comes to generic engine
82functionality. Not that many fundamental (conceptual) extensions showed up over
83the last few decades so no one will bother if in \LUAMETATEX\ we have new stuff
84that is only used by \CONTEXT. The example code shown here gives:
85
86\startbuffer[four]
87\startcombination[4*1]
88    {\scale[sx=.4,sy=.4]{\TestMe{0}}} {\type {orientation 0}}
89    {\scale[sx=.4,sy=.4]{\TestMe{1}}} {\type {orientation 1}}
90    {\scale[sx=.4,sy=.4]{\TestMe{2}}} {\type {orientation 2}}
91    {\scale[sx=.4,sy=.4]{\TestMe{3}}} {\type {orientation 3}}
92\stopcombination
93\stopbuffer
94
95\startlinecorrection
96\dontcomplain\getbuffer[four]
97\stoplinecorrection
98
99In order to avoid additional shifting around, which then might involve copying
100and injecting boxes as well as repackaging, two additional keys are available
101and these deal with the way boxes get anchored.
102
103\startbuffer
104\vbox
105    source 123
106    \bgroup
107        \offinterlineskip
108        \blackrule[width=4cm,height=2cm,depth=0cm,color=darkred]\par
109        \blackrule[width=4cm,height=0cm,depth=1cm,color=darkblue]\par
110        \setbox\scratchboxtwo\hbox
111            anchors "0004 "0001
112          % anchor "00040001
113            target 123
114            orientation 1
115            {\blackrule[width=2cm,height=1cm,depth=0cm,color=darkgreen]%
116             \hskip-2cm
117             \blackrule[width=2cm,height=0cm,depth=1cm,color=darkyellow]}%
118          %
119        \smash{\box\scratchboxtwo}%
120    \egroup
121\stopbuffer
122
123\typebuffer
124
125The anchor is just an number but with the plural keyword we can scan it as two
126because that is a bit easier on usage. The two numbers four byte numbers control
127the source to target anchoring and there is plenty room for future extensions
128because not all bits are used.
129
130\starttabulate[|lT|lT|]
131\NC 0x00\uchexnumber\leftoriginlistanchorcode    \NC left    origin \NC \NR
132\NC 0x00\uchexnumber\leftheightlistanchorcode    \NC left    height \NC \NR
133\NC 0x00\uchexnumber\leftdepthlistanchorcode     \NC left    depth  \NC \NR
134\NC 0x00\uchexnumber\rightoriginlistanchorcode   \NC right   origin \NC \NR
135\NC 0x00\uchexnumber\rightheightlistanchorcode   \NC right   height \NC \NR
136\NC 0x00\uchexnumber\rightdepthlistanchorcode    \NC right   depth  \NC \NR
137\NC 0x00\uchexnumber\centeroriginlistanchorcode  \NC center  origin \NC \NR
138\NC 0x00\uchexnumber\centerheightlistanchorcode  \NC center  height \NC \NR
139\NC 0x00\uchexnumber\centerdepthlistanchorcode   \NC center  depth  \NC \NR
140\NC 0x00\uchexnumber\halfwaytotallistanchorcode  \NC halfway total  \NC \NR
141\NC 0x00\uchexnumber\halfwayheightlistanchorcode \NC halfway height \NC \NR
142\NC 0x00\uchexnumber\halfwaydepthlistanchorcode  \NC halfway depth  \NC \NR
143\NC 0x00\uchexnumber\halfwayleftlistanchorcode   \NC halfway left   \NC \NR
144\NC 0x00\uchexnumber\halfwayrightlistanchorcode  \NC halfway right  \NC \NR
145\stoptabulate
146
147The target and source are handled in a way that sort of naturally binds them
148which involves a little juggling with dimensions in the backend. There is some
149additional control over this but usage is not advertized here because it might
150change.
151
152% \negatexlistsigncode \negateylistsigncode \negatelistsigncode
153
154One can set these anchoring related properties with keywords but there are also
155primitive box manipulators: \type {\boxanchor}, \type {\boxanchors}, \type
156{\boxsource} and \type {\boxtarget} that take a box number and value.
157
158\startlinecorrection
159\getbuffer
160\stoplinecorrection
161
162There are some helpers at the \LUA\ end but I haven't completely made up my mind
163about them. Normally that evolves with usage.
164
165\stopsection
166
167\startsection[title={A first higher level interface}]
168
169Exploring this here in more detail makes no sense because it is still
170experimental and also rather \CONTEXT\ specific. As a teaser an interface that
171hooks into layers is shown:
172
173\startbuffer
174\defineanchorboxoverlay[framed]
175
176\def\DemoAnchor#1#2#3#4%
177  {\setanchorbox
178     [#1]%
179     [target={#3},source={#4}]%
180     \hbox{\backgroundline[#2]{\white\smallinfofont\setstrut\strut target=#3 source=#4}}}
181
182\def\DemoAnchorX#1#2%
183  {\DemoAnchor{#1}{darkred}   {#2}{left,top}%
184   \DemoAnchor{#1}{darkblue}  {#2}{left,bottom}%
185   \DemoAnchor{#1}{darkgreen} {#2}{right,bottom}%
186   \DemoAnchor{#1}{darkyellow}{#2}{right,top}%
187   }%
188
189\startsetups framed:demo
190    \DemoAnchorX{framed:background}{left,top}%
191    \DemoAnchorX{framed:background}{right,top}%
192    \DemoAnchorX{framed:background}{left,bottom}%
193    \DemoAnchorX{framed:background}{right,bottom}%
194    \DemoAnchorX{framed:foreground}{middle}%
195\stopsetups
196
197\midaligned\bgroup
198    \framed
199      [align=normal,
200       width=.7\textwidth,
201       backgroundcolor=gray,
202       background={color,framed:background,foreground,framed:foreground}]
203      \bgroup
204        \samplefile{zapf}\par
205        \directsetup{framed:demo}%
206        \samplefile{zapf}%
207      \egroup
208\egroup
209\stopbuffer
210
211\typebuffer
212
213Those familiar with \CONTEXT\ will recognize the approach. This one basically is
214a more low level variant of layers and a high level variant of the primitives.
215Performance wise (in terms of memory usage and runtime) it sits in a sweet spot.
216
217\startlinecorrection[2*big]
218    \getbuffer
219\stoplinecorrection
220
221I played a bit with a mechanism that can store the embedded (to be anchored)
222content in a more independent way and it actually works okay. However, I'm not
223entirely sure if that solution is the best so for now it's commented. As usual it
224is also up to users to come up with demands.
225
226\stopsection
227
228\stopchapter
229
230\stopcomponent
231
232% \defineanchorbox[page:background]
233% \defineanchorbox[page:foreground]
234% \defineoverlay[page:background][\overlayanchorbox{page:background}]
235% \defineoverlay[page:foreground][\overlayanchorbox{page:foreground}]
236%
237% \defineanchorboxoverlay[page]
238%
239% \setupbackgrounds[page][background={page:background,foreground,page:foreground}]
240%
241% test
242%
243% \setanchorbox[page:background]\ruledhbox
244%     xoffset 200pt
245%     yoffset 100pt
246% %     anchors  \halfwayleftlistanchorcode \halfwayrightlistanchorcode
247%     {\blue DOES IT WORK}
248%
249% \setanchorbox[page:foreground]\ruledhbox
250%     orientation 2
251% %     anchors  \halfwayleftlistanchorcode \halfwayrightlistanchorcode
252%     {\red DOES IT WORK}
253%
254
255% \registeranchorbox[demo][before]\ruledhbox
256% \registeranchorbox[demo][after]\ruledhbox
257%
258% \defineanchorbox[demo]
259%
260% \startbuffer
261% \vbox
262%     source 123
263%     \bgroup
264%         \offinterlineskip
265%         \blackrule[width=4cm,height=2cm,depth=0cm,color=darkred]\par
266%         \blackrule[width=4cm,height=0cm,depth=1cm,color=darkblue]\par
267%         \registeranchorbox[demo][before]\ruledhbox
268%       % \registeranchorbox[demo][after]\ruledhbox
269%             anchors "0004 "0001
270%           % anchor "00040001
271%             target 123
272%             orientation 1
273%             {\blackrule[width=2cm,height=1cm,depth=0cm,color=darkgreen]%
274%              \hskip-2cm
275%              \blackrule[width=2cm,height=0cm,depth=1cm,color=darkyellow]}%
276%           %
277%     \egroup
278% \stopbuffer
279%
280% \typebuffer
281