summaryrefslogtreecommitdiff
path: root/doc/context/sources/general/manuals/ontarget/ontarget-anchoring.tex
blob: 4cdb72950993c48d01a63bd99ae68572373293cd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
% language=us runpath=texruns:manuals/ontarget

\startcomponent ontarget-eventually

\environment ontarget-style

\startchapter[title={Anchoring}]

\startsection[title=Introduction]

It is valid to question what functionality should be in the engine and what can
best be implemented using callbacks and postprocessing of lists (and boxes)
relying for instance on attributes as signals. In \LUATEX\ we are rather strict
in this and assume that the second method is used. In \LUAMETATEX\ we still
promote this but at the same time some (lightweight) functionality has been added
to the engine that helps implementing some features more efficiently. Reasons are
that it can be handy to carry (fundamental) properties around that are bound to
nodes and that we can set them using primitives, especially for glyphs and boxes.
That way they become part of the formal functionality that one can argue should
be present in a modern engine. Examples for glyph nodes are scales, offsets and
hyphenation, detailed ligature and kerning control. For box nodes we have for
instance offsets and orientation. Most of these are always taken into account by
core mechanisms like breaking paragraphs into lines, where dimensions matter in
which case it really makes sense for them to be part of the engine design.

Some properties are just passed on to for instance a font handler or the backend
but still they belong to the core functionality. An example of the later is a
(new) simple mechanism for anchoring boxes. This is not really a fundamental
feature, because one can just move content around using a combination of kerning
and boxing, either or not with offsets. But because we already have features like
offsets to boxes it was not that much work to add anchoring as a more fundamental
property. The frontend is agnostic to this feature because dimensions are kind of
virtual here: the backend however carries the real burden. Because backends are
written in \LUA\ it might have a performance hit simply because at least we need
to check if this feature is used. Normally that can compensated when this feature
{\em is} used because less work and shuffling around happens in the frontend. And
when this feature is no longer experimental (and stays) we can gain some back by
using it in existing scenarios. It sounds worse than it is because for
orientations we already have to do some usage checking and we can share that
check; in most situations nothing needs to be done anyway.

\stopsection

\startsection[title=The low level approach]

When we anchor, a box can be a source and|/|or a target. Both are represented by
a number and can be assigned via a keyword. These numbers can be picked up by the
backend. Here is an example:

\startbuffer
\def\TestMe#1{%
    \setbox \scratchbox \ruledvbox
        source 123
        orientation #1
        \bgroup
            \hsize7cm
            \samplefile{zapf}
            \hbox to 0pt
                source 124 target 123
                xoffset 20pt yoffset -30pt
                {\darkred \bfc TEST1}%
            \hbox to 0pt
                source 125 target 124
                xoffset 10pt yoffset -20pt
                {\darkblue \bfc TEST2}%
        \egroup
    \box \scratchbox
}
\stopbuffer

\typebuffer \getbuffer

This example also uses a few offsets. The \quote {origin} is at the left edge of
the baseline. Now, we could have passed the source and target as attribute and
intercepting an attribute in the backend can work pretty well. However, the code
that deals with the final result of the typesetting and thereby flushes it to for
instance a \PDF\ file is, at least that is the setup we use in \CONTEXT,
attribute agnostic. Mixing in attributes at that stage, except for user nodes and
whatsits that are effectively plugins, is counter intuitive and all is already
pretty complex so a clear separation of functionality makes a lot of sense. Of
course the \CONTEXT\ approach is not the only one when it comes to generic engine
functionality. Not that many fundamental (conceptual) extensions showed up over
the last few decades so no one will bother if in \LUAMETATEX\ we have new stuff
that is only used by \CONTEXT. The example code shown here gives:

\startbuffer[four]
\startcombination[4*1]
    {\scale[sx=.4,sy=.4]{\TestMe{0}}} {\type {orientation 0}}
    {\scale[sx=.4,sy=.4]{\TestMe{1}}} {\type {orientation 1}}
    {\scale[sx=.4,sy=.4]{\TestMe{2}}} {\type {orientation 2}}
    {\scale[sx=.4,sy=.4]{\TestMe{3}}} {\type {orientation 3}}
\stopcombination
\stopbuffer

\startlinecorrection
\dontcomplain\getbuffer[four]
\stoplinecorrection

In order to avoid additional shifting around, which then might involve copying
and injecting boxes as well as repackaging, two additional keys are available
and these deal with the way boxes get anchored.

\startbuffer
\vbox
    source 123
    \bgroup
        \offinterlineskip
        \blackrule[width=4cm,height=2cm,depth=0cm,color=darkred]\par
        \blackrule[width=4cm,height=0cm,depth=1cm,color=darkblue]\par
        \setbox\scratchboxtwo\hbox
            anchors "0004 "0001
          % anchor "00040001
            target 123
            orientation 1
            {\blackrule[width=2cm,height=1cm,depth=0cm,color=darkgreen]%
             \hskip-2cm
             \blackrule[width=2cm,height=0cm,depth=1cm,color=darkyellow]}%
          %
        \smash{\box\scratchboxtwo}%
    \egroup
\stopbuffer

\typebuffer

The anchor is just an number but with the plural keyword we can scan it as two
because that is a bit easier on usage. The two numbers four byte numbers control
the source to target anchoring and there is plenty room for future extensions
because not all bits are used.

\starttabulate[|lT|lT|]
\NC 0x00\uchexnumber\leftoriginlistanchorcode    \NC left    origin \NC \NR
\NC 0x00\uchexnumber\leftheightlistanchorcode    \NC left    height \NC \NR
\NC 0x00\uchexnumber\leftdepthlistanchorcode     \NC left    depth  \NC \NR
\NC 0x00\uchexnumber\rightoriginlistanchorcode   \NC right   origin \NC \NR
\NC 0x00\uchexnumber\rightheightlistanchorcode   \NC right   height \NC \NR
\NC 0x00\uchexnumber\rightdepthlistanchorcode    \NC right   depth  \NC \NR
\NC 0x00\uchexnumber\centeroriginlistanchorcode  \NC center  origin \NC \NR
\NC 0x00\uchexnumber\centerheightlistanchorcode  \NC center  height \NC \NR
\NC 0x00\uchexnumber\centerdepthlistanchorcode   \NC center  depth  \NC \NR
\NC 0x00\uchexnumber\halfwaytotallistanchorcode  \NC halfway total  \NC \NR
\NC 0x00\uchexnumber\halfwayheightlistanchorcode \NC halfway height \NC \NR
\NC 0x00\uchexnumber\halfwaydepthlistanchorcode  \NC halfway depth  \NC \NR
\NC 0x00\uchexnumber\halfwayleftlistanchorcode   \NC halfway left   \NC \NR
\NC 0x00\uchexnumber\halfwayrightlistanchorcode  \NC halfway right  \NC \NR
\stoptabulate

The target and source are handled in a way that sort of naturally binds them
which involves a little juggling with dimensions in the backend. There is some
additional control over this but usage is not advertized here because it might
change.

% \negatexlistsigncode \negateylistsigncode \negatelistsigncode

One can set these anchoring related properties with keywords but there are also
primitive box manipulators: \type {\boxanchor}, \type {\boxanchors}, \type
{\boxsource} and \type {\boxtarget} that take a box number and value.

\startlinecorrection
\getbuffer
\stoplinecorrection

There are some helpers at the \LUA\ end but I haven't completely made up my mind
about them. Normally that evolves with usage.

\stopsection

\startsection[title={A first higher level interface}]

Exploring this here in more detail makes no sense because it is still
experimental and also rather \CONTEXT\ specific. As a teaser an interface that
hooks into layers is shown:

\startbuffer
\defineanchorboxoverlay[framed]

\def\DemoAnchor#1#2#3#4%
  {\setanchorbox
     [#1]%
     [target={#3},source={#4}]%
     \hbox{\backgroundline[#2]{\white\smallinfofont\setstrut\strut target=#3 source=#4}}}

\def\DemoAnchorX#1#2%
  {\DemoAnchor{#1}{darkred}   {#2}{left,top}%
   \DemoAnchor{#1}{darkblue}  {#2}{left,bottom}%
   \DemoAnchor{#1}{darkgreen} {#2}{right,bottom}%
   \DemoAnchor{#1}{darkyellow}{#2}{right,top}%
   }%

\startsetups framed:demo
    \DemoAnchorX{framed:background}{left,top}%
    \DemoAnchorX{framed:background}{right,top}%
    \DemoAnchorX{framed:background}{left,bottom}%
    \DemoAnchorX{framed:background}{right,bottom}%
    \DemoAnchorX{framed:foreground}{middle}%
\stopsetups

\midaligned\bgroup
    \framed
      [align=normal,
       width=.7\textwidth,
       backgroundcolor=gray,
       background={color,framed:background,foreground,framed:foreground}]
      \bgroup
        \samplefile{zapf}\par
        \directsetup{framed:demo}%
        \samplefile{zapf}%
      \egroup
\egroup
\stopbuffer

\typebuffer

Those familiar with \CONTEXT\ will recognize the approach. This one basically is
a more low level variant of layers and a high level variant of the primitives.
Performance wise (in terms of memory usage and runtime) it sits in a sweet spot.

\startlinecorrection[2*big]
    \getbuffer
\stoplinecorrection

I played a bit with a mechanism that can store the embedded (to be anchored)
content in a more independent way and it actually works okay. However, I'm not
entirely sure if that solution is the best so for now it's commented. As usual it
is also up to users to come up with demands.

\stopsection

\stopchapter

\stopcomponent

% \defineanchorbox[page:background]
% \defineanchorbox[page:foreground]
% \defineoverlay[page:background][\overlayanchorbox{page:background}]
% \defineoverlay[page:foreground][\overlayanchorbox{page:foreground}]
%
% \defineanchorboxoverlay[page]
%
% \setupbackgrounds[page][background={page:background,foreground,page:foreground}]
%
% test
%
% \setanchorbox[page:background]\ruledhbox
%     xoffset 200pt
%     yoffset 100pt
% %     anchors  \halfwayleftlistanchorcode \halfwayrightlistanchorcode
%     {\blue DOES IT WORK}
%
% \setanchorbox[page:foreground]\ruledhbox
%     orientation 2
% %     anchors  \halfwayleftlistanchorcode \halfwayrightlistanchorcode
%     {\red DOES IT WORK}
%

% \registeranchorbox[demo][before]\ruledhbox
% \registeranchorbox[demo][after]\ruledhbox
%
% \defineanchorbox[demo]
%
% \startbuffer
% \vbox
%     source 123
%     \bgroup
%         \offinterlineskip
%         \blackrule[width=4cm,height=2cm,depth=0cm,color=darkred]\par
%         \blackrule[width=4cm,height=0cm,depth=1cm,color=darkblue]\par
%         \registeranchorbox[demo][before]\ruledhbox
%       % \registeranchorbox[demo][after]\ruledhbox
%             anchors "0004 "0001
%           % anchor "00040001
%             target 123
%             orientation 1
%             {\blackrule[width=2cm,height=1cm,depth=0cm,color=darkgreen]%
%              \hskip-2cm
%              \blackrule[width=2cm,height=0cm,depth=1cm,color=darkyellow]}%
%           %
%     \egroup
% \stopbuffer
%
% \typebuffer