anch-pgr.mkxl /size: 15 Kb    last modification: 2023-12-21 09:44
1%D \module
2%D   [       file=anch-pgr, % split off core-pos
3%D        version=1999.08.01,
4%D          title=\CONTEXT\ Anchoring Macros,
5%D       subtitle=Positioning Graphics,
6%D         author=Hans Hagen,
7%D           date=\currentdate,
8%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
9%C
10%C This module is part of the \CONTEXT\ macro||package and is
11%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
12%C details.
13
14\writestatus{loading}{ConTeXt Anchoring Macros / Grapics}
15
16%D Before we come to graphics support, we have to make sure of the reference point
17%D on the page. The next macros do so and are hooked into the page building routine.
18
19\registerctxluafile{anch-pgr}{autosuffix}
20
21\unprotect
22
23%D A few more low level macros take care of defining and recalling actions. Actions
24%D are saved globally! The lists can become quite long because there can be lots of
25%D parameters passed on so we clean up the list afterwards.
26
27\newtoks\everypositionaction
28\newtoks\everyinsertpositionaction
29\newtoks\everycleanpositionaction
30
31\installcorenamespace{positionaction}
32\installcorenamespace{positioncleanup}
33
34\protected\def\anch_positions_set_action#1%
35  {\gdefcsname\??positionaction#1\endcsname} % nicely gobbles spaces
36
37\permanent\protected\def\doifpositionaction#1%
38  {\ifcsname\??positionaction#1\endcsname
39     \expandafter\firstofoneargument
40   \else
41     \expandafter\gobbleoneargument
42   \fi}
43
44\permanent\protected\def\doifelsepositionaction#1%
45  {\ifcsname\??positionaction#1\endcsname
46     \expandafter\firstoftwoarguments
47   \else
48     \expandafter\secondoftwoarguments
49   \fi}
50
51\aliased\let\doifpositionactionelse\doifelsepositionaction
52
53\permanent\protected\def\dopositionaction#1%
54  {\cdef\currentpositionaction{#1}%
55   \ifcsname\??positionaction\currentpositionaction\endcsname
56     \anch_positions_action_indeed
57   \fi}
58
59\def\anch_positions_action_indeed
60  {\doifelseposition\currentpositionaction
61     \anch_positions_action_indeed_yes
62     \anch_positions_action_indeed_nop}
63
64\def\anch_positions_action_indeed_nop
65  {\anch_positions_trace_action_nop}
66
67\def\anch_positions_action_indeed_yes % we need a way to figure out if we have actions
68  {\begingroup
69   \setbox\scratchbox\hbox % \hpack
70     {\anch_positions_trace_action_yes
71      \expand\everyinsertpositionaction
72      \expand\everypositionaction
73      \begincsname\??positionaction\currentpositionaction\endcsname
74      \anch_positions_cleanup_action}%
75   \smashedbox\scratchbox % smashing is really needed else we get problems with too big overlays
76   \endgroup}
77
78\protected\def\anch_positions_trace_action_nop_indeed
79  {\anch_positions_trace\clap\darkred{<\currentpositionaction>}}
80
81\protected\def\anch_positions_trace_action_yes_indeed
82  {\anch_positions_trace\clap\darkgreen{<\currentpositionaction>}}
83
84\let\anch_positions_trace_action_nop\relax
85\let\anch_positions_trace_action_yes\relax
86
87\appendtoks
88    \let\anch_positions_trace_action_nop\anch_positions_trace_action_nop_indeed
89    \let\anch_positions_trace_action_yes\anch_positions_trace_action_yes_indeed
90\to \t_anch_positions_tracers
91
92%D Here the complication has to do with collecting actions for later execution. This
93%D collection is especially handy when we want to move actions to a specific layer.
94%D Such series of actions are stored in a macro that is cleaned up after each
95%D invocation.
96
97\def\anch_positions_cleanup_action % not in trialtypesetting
98  {\ifcsname\??positioncleanup\currentpositionaction\endcsname
99     \expand\everycleanpositionaction
100     \xdefcsname\??positioncleanup\currentpositionaction\endcsname{\csname\??positioncleanup\currentpositionaction\endcsname}%
101   \fi}
102
103\permanent\protected\def\handlepositionaction#1\with#2\on#3% ugly, will change
104  {\begingroup
105   \cdef\currentpositionanchor{\ifempty\currentpositionoverlay#3\else\currentpositionoverlay::\MPanchoridentifier\fi}%
106   \normalexpanded{\anch_positions_set_action{\currentpositionanchor}{\noexpand\csname\??positioncleanup\currentpositionanchor\endcsname}}%
107   \let#1\relax
108   \ifcsname\??positioncleanup\currentpositionanchor\endcsname
109     \xdefcsname\??positioncleanup\currentpositionanchor\endcsname{\csname\??positioncleanup\currentpositionanchor\endcsname#1#2}%
110   \else
111     \xdefcsname\??positioncleanup\currentpositionanchor\endcsname{#1#2}%
112   \fi
113   \endgroup}
114
115%D The first version of this module implemented head and tail anchors. Currently we
116%D stick to just one anchor and derive the head and tail anchors from this one. We
117%D set these anchors before and after each page.
118
119\newdimension\c_anch_page_width
120\newdimension\c_anch_page_height
121
122\protected\def\anch_positions_register_page#1% this one is flushed first ! ... can't we avoid this one
123  {\ifpositioning\ifcase\realpageno\or
124     \ifdim\c_anch_page_height=\paperheight
125       \ifdim\c_anch_page_width=\paperwidth
126         % no change
127       \else
128         \c_anch_page_width \paperwidth
129         \c_anch_page_height\paperheight
130         \anch_make_page_box{#1}% \ifvbox#1\setbox#1\hpack{\box#1}\fi
131       \fi
132     \else
133       \c_anch_page_width \paperwidth
134       \c_anch_page_height\paperheight
135       \anch_make_page_box{#1}% \ifvbox#1\setbox#1\hpack{\box#1}\fi
136     \fi
137   \fi\fi}
138
139\protected\def\anch_positions_place_anchors
140  {\ifpositioning
141     \anch_positions_place_anchors_yes
142   \else
143     \anch_positions_place_anchors_nop
144   \fi}
145
146\def\anch_positions_place_anchors_yes % todo : depth pagebox
147  {\begingroup
148   \setbox\scratchbox\emptyhbox
149   \ht\scratchbox\textheight
150   \dp\scratchbox\zeropoint % redundant
151   \wd\scratchbox\makeupwidth
152   \anch_mark_text_box\scratchbox
153   \box\scratchbox
154   \endgroup}
155
156\def\anch_positions_place_anchors_nop
157  {\vkern\textheight}
158
159%D \macros
160%D   {positionoverlay,startpositionoverlay}
161%D
162%D As long as we're dealing with graphics it makes much sense to use the available
163%D overlay mechanism. For this purpose, we define some dedicated overlay extensions.
164%D
165%D \startbuffer[sample]
166%D \defineoverlay [sample] [\positionoverlay{sample}]
167%D
168%D \startpositionoverlay{sample}
169%D   \setMPpositiongraphic{A-1}{connectcenter}{from=A-1,to=A-2}
170%D \stoppositionoverlay
171%D \stopbuffer
172%D
173%D \typebuffer[sample]
174%D
175%D \startbuffer[graphic]
176%D \startMPpositiongraphic{connectcenter}
177%D   path pa, pb ; pair ca, cb ;
178%D   initialize_box(\MPpos{\MPvar{from}}) ; pa := pxy ; ca := cxy ;
179%D   initialize_box(\MPpos{\MPvar{to}}) ; pb := pxy ; cb := cxy ;
180%D   draw pa withcolor red ;
181%D   draw pb withcolor red ;
182%D   draw ca -- cb withcolor blue ;
183%D   anchor_box(\MPanchor{\MPvar{from}}) ;
184%D \stopMPpositiongraphic
185%D \stopbuffer
186%D
187%D We can best demonstrate this in an example, say:
188%D
189%D \startbuffer[text]
190%D \framed
191%D   [backgroundachtergrond=sample,align=middle,width=7cm]
192%D   {We want to connect \hpos {A-1} {this} word with its
193%D    grammatical cousin \hpos {A-2} {that}.}
194%D \stopbuffer
195%D
196%D \typebuffer[text]
197%D
198%D \startlinecorrection
199%D %\getbuffer[graphic,sample,text]
200%D \stoplinecorrection
201%D
202%D The graphic is defined in the following way, using some macros defined in an
203%D auxiliary \METAPOST\ module that is preloaded.
204%D
205%D \typebuffer[graphic]
206
207\immutable\def         \MPanchoridentifier{mpa}  % {mp-anchor}
208\mutable  \def         \MPanchornumber    {\the\realpageno}
209\mutable  \lettonothing\MPanchorid
210
211%D The rest of the definitions concerning such overlays may look complicated,
212
213\mutable\lettonothing\currentpositionoverlay
214
215%D Position actions are automatically executed when a position is set.
216
217\immutable\def\textbackgroundoverlay#1{\v!text#1}
218
219\permanent\protected\def\positionoverlay % the test prevents too many redundant positions
220  {\ifpositioning               % in (not used) text* position layers
221     \expandafter\anch_positions_overlay_indeed
222   \else % also \iftrialtypesetting test here?
223     \expandafter\gobbleoneargument
224   \fi}
225
226\def\anch_positions_overlay_indeed#1%
227  {\begingroup
228   \cdef\currentpositionoverlay{#1}%
229   \ifcsname\??positionaction\currentpositionoverlay::\MPanchoridentifier\endcsname
230     \anch_positions_overlay_compose
231   \fi
232   \endgroup}
233
234\permanent\def\MPoverlayanchor#1{\MPpos\MPanchorid}
235
236\def\anch_positions_overlay_compose
237  {\vpack to \d_overlay_height
238     {%\writestatus{!!!}{\currentpositionoverlay/\MPanchoridentifier/\MPanchornumber}%
239      \edef\MPanchorid{\currentpositionoverlay::\MPanchoridentifier:\MPanchornumber}% realpageno
240    % \edef\MPanchor##1{\MPpos\MPanchorid}%
241      \enforced\let\MPanchor\MPoverlayanchor % no need to fetch it already, seldom used
242      \expand\everyinsertpositionaction
243      \copyposition{\currentpositionoverlay::\MPanchoridentifier}\MPanchorid
244      \setbox\scratchbox\hbox to \d_overlay_width % \hpack
245        {\dopositionaction{\currentpositionoverlay::\MPanchoridentifier}\hss}%
246      \ht\scratchbox\d_overlay_height
247      \dp\scratchbox\zeropoint
248      \anch_mark_tagged_box\scratchbox\MPanchorid\zerocount % needs an hbox
249      \box\scratchbox
250      \vfill}}
251
252\permanent\protected\def\positionregionoverlay  % shares regions
253  {\ifpositioning
254     \expandafter\anch_positions_region_overlay_indeed
255   \else % also \iftrialtypesetting test here?
256     \expandafter\gobbletwoarguments
257   \fi}
258
259\lettonothing\currentpositionregion
260
261\def\anch_positions_region_overlay_indeed#1#2%
262  {\begingroup
263   \cdef\currentpositionregion {#1}%
264   \cdef\currentpositionoverlay{#2}%
265   \ifcsname\??positionaction\currentpositionoverlay::\MPanchoridentifier\endcsname
266     \anch_positions_region_overlay_compose
267   \fi
268   \endgroup}
269
270\def\anch_positions_region_overlay_compose
271  {\vpack to \d_overlay_height
272     {\let\MPanchorid\currentpositionregion
273      \enforced\let\MPanchor\MPoverlayanchor % no need to fetch it already, seldom used
274      \expand\everyinsertpositionaction
275      \copyposition{\currentpositionoverlay::\MPanchoridentifier}\MPanchorid
276      \setbox\scratchbox\hbox to \d_overlay_width % \hpack
277        {\dopositionaction{\currentpositionoverlay::\MPanchoridentifier}\hss}%
278      \ht\scratchbox\d_overlay_height
279      \dp\scratchbox\zeropoint
280      \box\scratchbox
281      \vfill}}
282
283% \let\anch_positions_overlay_nop\gobbleoneargument
284
285\permanent\protected\def\startpositionoverlay
286  {\iftrialtypesetting
287     \expandafter\anch_positions_overlay_start_nop
288   \else
289     \expandafter\anch_positions_overlay_start_yes
290   \fi}
291
292\def\anch_positions_overlay_start_nop#1\stoppositionoverlay
293  {}
294
295\ifdefined\checkpositionoverlays \else \let\checkpositionoverlays\relax \fi
296
297\mutable\lettonothing\currentpositionoverlay
298
299\def\anch_positions_overlay_start_yes#1%
300  {\checkpositionoverlays
301   \cdef\currentpositionoverlay{#1}}
302
303\permanent\protected\def\stoppositionoverlay
304  {\lettonothing\currentpositionoverlay}
305
306%D A position graphic is a normal (non||reused) \METAPOST\ graphic, used
307%D immediately, with zero dimensions, so that a sequence of them does not harm.
308
309\installcorenamespace{positiongraphic}
310\installcorenamespace{positionmethod}
311%installcorenamespace{graphicvariable}
312
313\newbox\b_anch_positions_graphic
314
315\permanent\tolerant\protected\def\startMPpositiongraphic#=#*#=#:#3\stopMPpositiongraphic % tag list mpcode
316  {\gdefcsname\??positiongraphic#1\endcsname{\anch_positions_meta_graphic_use{#1}{#2}{#3}}}
317
318\permanent\protected\lettonothing\stopMPpositiongraphic
319
320\def\anch_positions_meta_graphic_prepare
321  {\ifempty{\mpcategoryparameter{self}}%
322     \letmpcategoryparameter{self}\currentposition
323   \fi
324   \ifempty{\mpcategoryparameter{from}}%
325     \letmpcategoryparameter{from}\currentposition
326   \fi}
327
328\def\anch_positions_meta_graphic_use#1#2#3%
329  {\begingroup
330   \cdef\currentmpcategory{#1}%
331   \anch_positions_meta_graphic_prepare
332   \startMPcode#3\stopMPcode
333   \endgroup}
334
335\permanent\tolerant\protected\def\MPpositiongraphic#=#*#=%
336  {\ifcsname\??positionmethod#1\endcsname % method
337     \expandafter\anch_positions_meta_graphic_direct_method
338   \orelse\ifcsname\??positiongraphic#1\endcsname
339     \expandafter\anch_positions_meta_graphic_direct_normal
340   \else
341     \expandafter\gobbletwoarguments
342   \fi{#1}{#2}}
343
344\def\anch_positions_meta_graphic_direct_method{\anch_positions_meta_graphic_direct\??positionmethod }
345\def\anch_positions_meta_graphic_direct_normal{\anch_positions_meta_graphic_direct\??positiongraphic}
346
347\def\anch_positions_meta_graphic_direct#1#2#3% what tag setups
348  {\begingroup
349   \cdef\currentmpcategory{#2}%
350   \setupcurrentmpcategory[#3]%
351   \anch_positions_meta_graphic_prepare
352   \obeyMPboxorigin % do we also set the size ? when needed this must be done in mp ... might change
353   \enforced\tolerant\protected\def\MPpositiongraphic##=##*##={\anch_positions_meta_graphic_nested{#3}{##1}{##2}}% takes two extra arguments
354 % \def\anch_positions_meta_graphic_direct{\anch_positions_meta_graphic_nested{#3}}% takes two extra arguments
355   \setbox\b_anch_positions_graphic\hpack
356     {\ignorespaces\begincsname#1#2\endcsname\removelastspace}%
357   \smashbox\b_anch_positions_graphic
358   \box\b_anch_positions_graphic
359   \endgroup}
360
361\def\anch_positions_meta_graphic_nested#1#2#3% nesting used in prikkels / pascal (might go away)
362  {\begingroup
363   \cdef\currentmpcategory{#2}%
364   \setupcurrentmpcategory[#1,#3]%
365   \anch_positions_meta_graphic_prepare
366   \begincsname\??positiongraphic#2\endcsname
367   \endgroup}%
368
369\permanent\def\startMPpositionmethod#1#2\stopMPpositionmethod
370  {\gdefcsname\??positionmethod#1\endcsname{#2}} % todo: var list here
371
372\permanent\protected\lettonothing\stopMPpositionmethod
373
374%D Simple one position graphics.
375
376\permanent\tolerant\protected\def\setMPpositiongraphic#=#*#=#*#=%
377  {\ifempty\currentpositionoverlay
378     \anch_positions_set_action{#1}{\MPpositiongraphic{#2}{#3}}%
379   \else % silly can be one
380     \anch_positions_meta_graphic_handle{#1}{#2}{#3}%
381   \fi}
382
383\def\anch_positions_meta_graphic_handle#1#2#3% combine with boxes
384  {\handlepositionaction\anch_positions_meta_graphic_handle_indeed\with{#1}{#2}{#3}\on{#2}}
385
386\def\anch_positions_meta_graphic_insert#1#2#3% pos tag setups
387  {\ifnum\MPp{#1}=\realpageno\relax % extra saveguard
388     \cdef\currentposition{#1}\MPpositiongraphic{#2}{#3}%
389   \fi}
390
391\let\anch_positions_meta_graphic_handle_indeed\relax
392
393\appendtoks
394    \let\anch_positions_meta_graphic_handle_indeed\anch_positions_meta_graphic_insert
395\to \everyinsertpositionaction
396
397\def\anch_positions_meta_graphic_cleanup#1#2#3% pos tag setups
398  {\ifnum\MPp{#1}<\realpageno \else
399     \noexpand\anch_positions_meta_graphic_handle_indeed{#1}{#2}{#3}%
400   \fi}
401
402\appendtoks
403    \let\anch_positions_meta_graphic_handle_indeed\anch_positions_meta_graphic_cleanup
404\to \everycleanpositionaction
405
406%D Graphics that span two positions (beware, does not cross pages).
407
408\permanent\tolerant\protected\def\setMPpositiongraphicrange#=#*#=#*#=#*#=%
409  {\ifempty\currentpositionoverlay
410     \anch_positions_set_action{#1}{\MPpositiongraphic{#3}{#4}}%
411   \else
412     \anch_positions_meta_graphic_handle_range{#1}{#2}{#3}{#4}%
413   \fi}
414
415\def\anch_positions_meta_graphic_handle_range#1#2#3#4%
416  {\handlepositionaction\anch_positions_meta_graphic_handle_range_indeed\with{#1}{#2}{#3}{#4}\on{#2}}
417
418\def\anch_positions_meta_graphic_insert_range#1#2#3#4% pos pos tag setups
419  {\clf_doifelserangeonpage{#1}{#2}\realpageno
420     {\cdef\currentposition{#1}%
421      \MPpositiongraphic{#3}{#4}}%
422     {}}
423
424\appendtoks
425    \let\anch_positions_meta_graphic_handle_range_indeed\anch_positions_meta_graphic_insert_range
426\to \everyinsertpositionaction
427
428\def\anch_positions_meta_graphic_cleanup_range#1#2#3#4% pos tag setups
429  {\ifnum\MPp{#2}<\realpageno \else
430     \noexpand\anch_positions_meta_graphic_handle_range_indeed{#1}{#2}{#3}{#4}%
431   \fi}
432
433\appendtoks
434    \let\anch_positions_meta_graphic_handle_range_indeed\anch_positions_meta_graphic_cleanup_range
435\to \everycleanpositionaction
436
437\let\anch_positions_meta_graphic_handle_range_indeed\gobblefourarguments
438
439% Helpers:
440
441\permanent\def\MPgetposboxes #1#2{\clf_fetchposboxes{#1}{#2}\realpageno}
442\permanent\def\MPgetmultipars#1#2{\clf_fetchmultipar{#1}{#2}\realpageno}
443
444\protect \endinput
445