anch-pgr.mkiv /size: 15 Kb    last modification: 2020-07-01 14:35
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}{}
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\unexpanded\def\anch_positions_set_action#1%
35  {\expandafter\gdef\csname\??positionaction#1\endcsname} % nicely gobbles spaces
36
37\unexpanded\def\doifpositionaction#1%
38  {\ifcsname\??positionaction#1\endcsname
39     \expandafter\firstofoneargument
40   \else
41     \expandafter\gobbleoneargument
42   \fi}
43
44\unexpanded\def\doifelsepositionaction#1%
45  {\ifcsname\??positionaction#1\endcsname
46     \expandafter\firstoftwoarguments
47   \else
48     \expandafter\secondoftwoarguments
49   \fi}
50
51\let\doifpositionactionelse\doifelsepositionaction
52
53\unexpanded\def\dopositionaction#1%
54  {\edef\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      \the\everyinsertpositionaction
72      \the\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\unexpanded\def\anch_positions_trace_action_nop_indeed
79  {\anch_positions_trace\clap\darkred{<\currentpositionaction>}}
80
81\unexpanded\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     \the\everycleanpositionaction
100     \setxvalue{\??positioncleanup\currentpositionaction}{\csname\??positioncleanup\currentpositionaction\endcsname}%
101   \fi}
102
103\def\handlepositionaction#1\with#2\on#3% ugly
104  {\begingroup
105   \edef\currentpositionanchor
106     {\ifx\currentpositionoverlay\empty#3\else\currentpositionoverlay::\MPanchoridentifier\fi}%
107   \normalexpanded{\anch_positions_set_action{\currentpositionanchor}{\noexpand\getvalue{\??positioncleanup\currentpositionanchor}}}%
108   \let#1\relax
109   \ifcsname\??positioncleanup\currentpositionanchor\endcsname
110     \setxvalue{\??positioncleanup\currentpositionanchor}%
111       {\csname\??positioncleanup\currentpositionanchor\endcsname#1#2}%
112   \else
113     \setxvalue{\??positioncleanup\currentpositionanchor}%
114       {#1#2}%
115   \fi
116   \endgroup}
117
118%D The first version of this module implemented head and tail anchors. Currently we
119%D stick to just one anchor and derive the head and tail anchors from this one. We
120%D set these anchors before and after each page.
121
122\newdimen\c_anch_page_width
123\newdimen\c_anch_page_height
124
125\unexpanded\def\anch_positions_register_page#1% this one is flushed first ! ... can't we avoid this one
126  {\ifpositioning\ifcase\realpageno\or
127     \ifdim\c_anch_page_height=\paperheight
128       \ifdim\c_anch_page_width=\paperwidth
129         % no change
130       \else
131         \c_anch_page_width \paperwidth
132         \c_anch_page_height\paperheight
133         \anch_make_page_box{#1}% \ifvbox#1\setbox#1\hpack{\box#1}\fi
134       \fi
135     \else
136       \c_anch_page_width \paperwidth
137       \c_anch_page_height\paperheight
138       \anch_make_page_box{#1}% \ifvbox#1\setbox#1\hpack{\box#1}\fi
139     \fi
140   \fi\fi}
141
142\unexpanded\def\anch_positions_place_anchors
143  {\ifpositioning
144     \anch_positions_place_anchors_yes
145   \else
146     \anch_positions_place_anchors_nop
147   \fi}
148
149\def\anch_positions_place_anchors_yes % todo : depth pagebox
150  {\begingroup
151   \setbox\scratchbox\emptyhbox
152   \ht\scratchbox\textheight
153   \dp\scratchbox\zeropoint % redundant
154   \wd\scratchbox\makeupwidth
155   \anch_mark_text_box\scratchbox
156   \box\scratchbox
157   \endgroup}
158
159\def\anch_positions_place_anchors_nop
160  {\vkern\textheight}
161
162%D \macros
163%D   {positionoverlay,startpositionoverlay}
164%D
165%D As long as we're dealing with graphics it makes much sense to use the available
166%D overlay mechanism. For this purpose, we define some dedicated overlay extensions.
167%D
168%D \startbuffer[sample]
169%D \defineoverlay [sample] [\positionoverlay{sample}]
170%D
171%D \startpositionoverlay{sample}
172%D   \setMPpositiongraphic{A-1}{connectcenter}{from=A-1,to=A-2}
173%D \stoppositionoverlay
174%D \stopbuffer
175%D
176%D \typebuffer[sample]
177%D
178%D \startbuffer[graphic]
179%D \startMPpositiongraphic{connectcenter}
180%D   path pa, pb ; pair ca, cb ;
181%D   initialize_box(\MPpos{\MPvar{from}}) ; pa := pxy ; ca := cxy ;
182%D   initialize_box(\MPpos{\MPvar{to}}) ; pb := pxy ; cb := cxy ;
183%D   draw pa withcolor red ;
184%D   draw pb withcolor red ;
185%D   draw ca -- cb withcolor blue ;
186%D   anchor_box(\MPanchor{\MPvar{from}}) ;
187%D \stopMPpositiongraphic
188%D \stopbuffer
189%D
190%D We can best demonstrate this in an example, say:
191%D
192%D \startbuffer[text]
193%D \framed
194%D   [backgroundachtergrond=sample,align=middle,width=7cm]
195%D   {We want to connect \hpos {A-1} {this} word with its
196%D    grammatical cousin \hpos {A-2} {that}.}
197%D \stopbuffer
198%D
199%D \typebuffer[text]
200%D
201%D \startlinecorrection
202%D %\getbuffer[graphic,sample,text]
203%D \stoplinecorrection
204%D
205%D The graphic is defined in the following way, using some macros defined in an
206%D auxiliary \METAPOST\ module that is preloaded.
207%D
208%D \typebuffer[graphic]
209
210\def\MPanchoridentifier{mpa}  % {mp-anchor}
211
212%D The rest of the definitions concerning such overlays may look complicated,
213
214\let\currentpositionoverlay\empty
215
216%D Position actions are automatically executed when a position is set.
217
218\def\textbackgroundoverlay#1{\v!text#1}
219\def\MPanchornumber         {\the\realpageno}
220
221\unexpanded\def\positionoverlay % the test prevents too many redundant positions
222  {\ifpositioning               % in (not used) text* position layers
223     \expandafter\anch_positions_overlay_indeed
224   \else % also \iftrialtypesetting test here?
225     \expandafter\gobbleoneargument
226   \fi}
227
228\def\anch_positions_overlay_indeed#1%
229  {\begingroup
230   \edef\currentpositionoverlay{#1}%
231   \ifcsname\??positionaction\currentpositionoverlay::\MPanchoridentifier\endcsname
232     \anch_positions_overlay_compose
233   \fi
234   \endgroup}
235
236\def\MPoverlayanchor#1{\MPpos\MPanchorid}
237
238\def\anch_positions_overlay_compose
239  {\vpack to \d_overlay_height
240     {%\writestatus{!!!}{\currentpositionoverlay/\MPanchoridentifier/\MPanchornumber}%
241      \edef\MPanchorid{\currentpositionoverlay::\MPanchoridentifier:\MPanchornumber}% realpageno
242    % \edef\MPanchor##1{\MPpos\MPanchorid}%
243      \let\MPanchor\MPoverlayanchor % no need to fetch it already, seldom used
244      \the\everyinsertpositionaction
245      \copyposition{\currentpositionoverlay::\MPanchoridentifier}\MPanchorid
246      \setbox\scratchbox\hbox to \d_overlay_width % \hpack
247        {\dopositionaction{\currentpositionoverlay::\MPanchoridentifier}\hss}%
248      \ht\scratchbox\d_overlay_height
249      \dp\scratchbox\zeropoint
250      \anch_mark_tagged_box\scratchbox\MPanchorid % needs an hbox
251      \box\scratchbox
252      \vfill}}
253
254\unexpanded\def\positionregionoverlay  % shares regions
255  {\ifpositioning
256     \expandafter\anch_positions_region_overlay_indeed
257   \else % also \iftrialtypesetting test here?
258     \expandafter\gobbletwoarguments
259   \fi}
260
261\let\currentpositionregion\empty
262
263\def\anch_positions_region_overlay_indeed#1#2%
264  {\begingroup
265   \edef\currentpositionregion {#1}%
266   \edef\currentpositionoverlay{#2}%
267   \ifcsname\??positionaction\currentpositionoverlay::\MPanchoridentifier\endcsname
268     \anch_positions_region_overlay_compose
269   \fi
270   \endgroup}
271
272\def\anch_positions_region_overlay_compose
273  {\vpack to \d_overlay_height
274     {\let\MPanchorid\currentpositionregion
275      \let\MPanchor\MPoverlayanchor % no need to fetch it already, seldom used
276      \the\everyinsertpositionaction
277      \copyposition{\currentpositionoverlay::\MPanchoridentifier}\MPanchorid
278      \setbox\scratchbox\hbox to \d_overlay_width % \hpack
279        {\dopositionaction{\currentpositionoverlay::\MPanchoridentifier}\hss}%
280      \ht\scratchbox\d_overlay_height
281      \dp\scratchbox\zeropoint
282      \box\scratchbox
283      \vfill}}
284
285% \let\anch_positions_overlay_nop\gobbleoneargument
286
287\unexpanded\def\startpositionoverlay
288  {\iftrialtypesetting
289     \expandafter\anch_positions_overlay_start_nop
290   \else
291     \expandafter\anch_positions_overlay_start_yes
292   \fi}
293
294\let\stoppositionoverlay\relax
295
296\def\anch_positions_overlay_start_nop#1\stoppositionoverlay
297  {}
298
299\ifdefined\checkpositionoverlays \else \let\checkpositionoverlays\relax \fi
300
301\let\currentpositionoverlay\empty
302
303\def\anch_positions_overlay_start_yes#1%
304  {\checkpositionoverlays
305   \edef\currentpositionoverlay{#1}}
306
307\unexpanded\def\stoppositionoverlay
308  {\let\currentpositionoverlay\empty}
309
310%D A position graphic is a normal (non||reused) \METAPOST\ graphic, used
311%D immediately, with zero dimensions, so that a sequence of them does not harm.
312
313\installcorenamespace{positiongraphic}
314\installcorenamespace{positionmethod}
315%installcorenamespace{graphicvariable}
316
317\newbox\b_anch_positions_graphic
318
319\def\startMPpositiongraphic % id setups
320  {\dodoublegroupempty\anch_positions_meta_graphic_start}
321
322\def\anch_positions_meta_graphic_start#1#2#3\stopMPpositiongraphic % tag list mpcode
323  {\setgvalue{\??positiongraphic#1}{\anch_positions_meta_graphic_use{#1}{#2}{#3}}}
324
325\let\stopMPpositiongraphic\relax
326
327\def\anch_positions_meta_graphic_prepare
328  {\ifcsname\??graphicvariable\currentmpvariableclass:self\endcsname \else
329     \letvalue{\??graphicvariable\currentmpvariableclass:self}\currentposition
330   \fi
331   \ifcsname\??graphicvariable\currentmpvariableclass:from\endcsname \else
332     \letvalue{\??graphicvariable\currentmpvariableclass:from}\currentposition
333   \fi}
334
335\def\anch_positions_meta_graphic_use#1#2#3%
336  {\begingroup
337   \meta_prepare_variables{#2}%
338   \anch_positions_meta_graphic_prepare
339   \startMPcode#3\stopMPcode
340   \endgroup}
341
342\unexpanded\def\MPpositiongraphic
343  {\dodoublegroupempty\anch_positions_meta_graphic_direct}
344
345\def\anch_positions_meta_graphic_direct#1% tag setups
346  {\ifcsname\??positionmethod#1\endcsname % method
347     \expandafter\anch_positions_meta_graphic_direct_indeed_method
348   \else\ifcsname\??positiongraphic#1\endcsname
349     \doubleexpandafter\anch_positions_meta_graphic_direct_indeed_normal
350   \else
351     \doubleexpandafter\anch_positions_meta_graphic_direct_indeed_unknown
352   \fi\fi{#1}}
353
354\let\anch_positions_meta_graphic_direct_indeed_unknown\gobbletwoarguments
355
356\def\anch_positions_meta_graphic_direct_indeed_method
357  {\anch_positions_meta_graphic_direct_indeed\??positionmethod}
358
359\def\anch_positions_meta_graphic_direct_indeed_normal
360  {\anch_positions_meta_graphic_direct_indeed\??positiongraphic}
361
362\def\anch_positions_meta_graphic_direct_indeed#1#2#3% what tag setups
363  {\begingroup
364   \setupMPvariables[#2][#3]%
365   \edef\currentmpvariableclass{#2}%
366   \anch_positions_meta_graphic_prepare
367   \obeyMPboxorigin % do we also set the size ? when needed this must be done in mp ... might change
368   \def\anch_positions_meta_graphic_direct{\anch_positions_meta_graphic_nested{#3}}% takes two extra arguments
369   \setbox\b_anch_positions_graphic\hbox % \hpack
370     {\ignorespaces\begincsname#1#2\endcsname\removelastspace}%
371   \smashbox\b_anch_positions_graphic
372   \box\b_anch_positions_graphic
373   \endgroup}
374
375\def\anch_positions_meta_graphic_nested#1#2#3% nesting used in prikkels / pascal (might go away)
376  {\begingroup
377   \setupMPvariables[#2][#1,#3]%
378   \edef\currentmpvariableclass{#2}%
379   \anch_positions_meta_graphic_prepare
380   \begincsname\??positiongraphic#2\endcsname
381   \endgroup}%
382
383\def\startMPpositionmethod#1#2\stopMPpositionmethod
384  {\setgvalue{\??positionmethod#1}{#2}} % todo: var list here
385
386\let\stopMPpositionmethod\relax
387
388%D Simple one position graphics.
389
390\unexpanded\def\setMPpositiongraphic
391  {\dotriplegroupempty\anch_positions_meta_graphic_set}
392
393\def\anch_positions_meta_graphic_set#1#2#3% pos tag vars
394  {\ifx\currentpositionoverlay\empty
395     \anch_positions_set_action{#1}{\MPpositiongraphic{#2}{#3}}%
396   \else % silly can be one
397     \anch_positions_meta_graphic_handle{#1}{#2}{#3}%
398   \fi}
399
400\def\anch_positions_meta_graphic_handle#1#2#3% combine with boxes
401  {\handlepositionaction\anch_positions_meta_graphic_handle_indeed\with{#1}{#2}{#3}\on{#2}}
402
403\def\anch_positions_meta_graphic_insert#1#2#3% pos tag setups
404  {\ifnum\MPp{#1}=\realpageno\relax % extra saveguard
405     \def\currentposition{#1}\MPpositiongraphic{#2}{#3}%
406   \fi}
407
408\let\anch_positions_meta_graphic_handle_indeed\relax
409
410\appendtoks
411    \let\anch_positions_meta_graphic_handle_indeed\anch_positions_meta_graphic_insert
412\to \everyinsertpositionaction
413
414\def\anch_positions_meta_graphic_cleanup#1#2#3% pos tag setups
415  {\ifnum\MPp{#1}<\realpageno \else
416     \noexpand\anch_positions_meta_graphic_handle_indeed{#1}{#2}{#3}%
417   \fi}
418
419\appendtoks
420    \let\anch_positions_meta_graphic_handle_indeed\anch_positions_meta_graphic_cleanup
421\to \everycleanpositionaction
422
423%D Graphics that span two positions (beware, does not cross pages).
424
425\unexpanded\def\setMPpositiongraphicrange
426  {\doquadruplegroupempty\anch_positions_meta_graphic_set_range}
427
428\def\anch_positions_meta_graphic_set_range#1#2#3#4% bpos epos tag vars
429  {\ifx\currentpositionoverlay\empty
430     \anch_positions_set_action{#1}{\MPpositiongraphic{#3}{#4}}%
431   \else
432     \anch_positions_meta_graphic_handle_range{#1}{#2}{#3}{#4}%
433   \fi}
434
435\def\anch_positions_meta_graphic_handle_range#1#2#3#4%
436  {\handlepositionaction\anch_positions_meta_graphic_handle_range_indeed\with{#1}{#2}{#3}{#4}\on{#2}}
437
438\def\anch_positions_meta_graphic_insert_range#1#2#3#4% pos pos tag setups
439  {\clf_doifelserangeonpage{#1}{#2}\realpageno
440     {\def\currentposition{#1}%
441      \MPpositiongraphic{#3}{#4}}%
442     {}}
443
444\appendtoks
445    \let\anch_positions_meta_graphic_handle_range_indeed\anch_positions_meta_graphic_insert_range
446\to \everyinsertpositionaction
447
448\def\anch_positions_meta_graphic_cleanup_range#1#2#3#4% pos tag setups
449  {\ifnum\MPp{#2}<\realpageno \else
450     \noexpand \anch_positions_meta_graphic_handle_range_indeed{#1}{#2}{#3}{#4}%
451   \fi}
452
453\appendtoks
454    \let\anch_positions_meta_graphic_handle_range_indeed\anch_positions_meta_graphic_cleanup_range
455\to \everycleanpositionaction
456
457\let\anch_positions_meta_graphic_handle_range_indeed\gobblefourarguments
458
459% Helpers:
460
461\def\MPgetposboxes #1#2{\clf_fetchposboxes{#1}{#2}\realpageno}
462\def\MPgetmultipars#1#2{\clf_fetchmultipar{#1}{#2}\realpageno}
463
464\protect \endinput
465