pack-box.mkxl /size: 47 Kb    last modification: 2023-12-21 09:44
1%D \module
2%D   [       file=pack-box,
3%D        version=2002.04.12,
4%D          title=\CONTEXT\ Packaging Macros,
5%D       subtitle=Boxes,
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 Packaging Macros / Boxes}
15
16%D This module contains all kind of macros for moving content around. Many
17%D macros here come from other modules, but depencies made it more clear
18%D to isolate them. We invite users to document the macros. They can be
19%D handy shortcuts for otherwise complex tasks.
20
21\unprotect
22
23%D We need to set the size, else we get dimensions depending on the content,
24%D which in itself is ok, but can lead to loops due to rounding errors (happened
25%D in demo-obv).
26
27% \definelayer[\v!text-2][\c!position=\v!yes,\c!region=,\c!width=\d_overlay_width,\c!height=\d_overlay_height]
28% \definelayer[\v!text-1][\c!position=\v!yes,\c!region=,\c!width=\d_overlay_width,\c!height=\d_overlay_height]
29% \definelayer[\v!text+1][\c!position=\v!yes,\c!region=,\c!width=\d_overlay_width,\c!height=\d_overlay_height]
30% \definelayer[\v!text+2][\c!position=\v!yes,\c!region=,\c!width=\d_overlay_width,\c!height=\d_overlay_height]
31
32\definelayer[\v!text-2][\c!position=\v!yes,\c!region=,\c!width=\textwidth,\c!height=\textheight]
33\definelayer[\v!text-1][\c!position=\v!yes,\c!region=,\c!width=\textwidth,\c!height=\textheight]
34\definelayer[\v!text+1][\c!position=\v!yes,\c!region=,\c!width=\textwidth,\c!height=\textheight]
35\definelayer[\v!text+2][\c!position=\v!yes,\c!region=,\c!width=\textwidth,\c!height=\textheight]
36
37\permanent\protected\def\internaltextoverlay#1% will become more generic and installable
38  {\startoverlay                     % i.e. probably an overlay by itself
39     {\positionregionoverlay\textanchor{\v!text#1}}% see later
40     {\composedlayer                   {\v!text#1}}%
41   \stopoverlay}
42
43\defineoverlay[\v!text-2][\internaltextoverlay{-2}]
44\defineoverlay[\v!text-1][\internaltextoverlay{-1}]
45\defineoverlay[\v!text+1][\internaltextoverlay{+1}]
46\defineoverlay[\v!text+2][\internaltextoverlay{+2}]
47
48\installcorenamespace {anchor}
49
50% produces a box too
51%
52% \anchor[text-1][preset=lefttop][framed settings]{HELLO WORLD}
53
54\mutable\lettonothing\currentanchor
55
56\permanent\tolerant\protected\def\defineanchor[#1]#*[#2]#*[#S#3]#*[#S#4]% name targetlayer layersetting framedsetting
57  {\defcsname\??anchor#1\endcsname{\pack_anchors_process_defined{#2}{#3}{#4}}}
58
59\let\pack_anchors_process_defined_indeed\gobbletwooptionals
60
61\def\pack_anchors_process_defined#1#2#3% brrr
62  {\tolerant\def\pack_anchors_process_defined_indeed[##S##1]##*[##S##2]%
63     {\ifarguments
64        \def\next{\pack_anchors_process_indeed{#1}{#2}{#3}}%
65      \or
66        \def\next{\pack_anchors_process_indeed{#1}{#2,##1}{#2,##1}}%
67      \or
68        \def\next{\pack_anchors_process_indeed{#1}{#2,##1}{#3,##2}}%
69      \fi
70      \next}% picks up a box
71   \pack_anchors_process_defined_indeed}
72
73\permanent\protected\def\anchor[#1]%
74  {\begingroup
75   \edef\currentanchor{#1}%
76   \ifcsname\??anchor\currentanchor\endcsname
77     \expandafter\lastnamedcs
78   \else
79     \expandafter\pack_anchor_notdefined
80   \fi}
81
82\tolerant\def\pack_anchor_notdefined[#1]#*[#2]%
83  {\ifarguments
84     \expandafter\gobbletwoarguments
85   \or
86     \expandafter\pack_anchor_notdefined_one
87   \else
88     \expandafter\pack_anchor_notdefined_two
89   \fi{#1}{#2}}
90
91\def\pack_anchor_notdefined_one   #1#2{\dowithnextbox{\pack_anchors_process_finish\currentanchor{#1}{#1}}\vbox}
92\def\pack_anchor_notdefined_two   #1#2{\dowithnextbox{\pack_anchors_process_finish\currentanchor{#1}{#2}}\vbox}
93\def\pack_anchors_process_indeed#1#2#3{\dowithnextbox{\pack_anchors_process_finish          {#1}{#2}{#3}}\vbox}
94
95\newbox      \b_pack_anchors
96\newdimension\d_pack_anchors_width
97\newdimension\d_pack_anchors_height
98\newdimension\d_pack_anchors_depth
99
100% \definelayer[anchor]
101
102\newinteger\c_pack_anchors_n
103\newtoks   \t_pack_anchors_flush
104
105\protected\def\pack_anchors_register#1#2%
106  {\global\advanceby\c_pack_anchors_n\plusone
107   \pagereference[\v!layer:\v!anchor:\the\c_pack_anchors_n]%
108   \putboxincache\v!anchor{\the\c_pack_anchors_n}\b_pack_anchors
109   \xtoksapp\t_pack_anchors_flush{\pack_anchors_flush{\the\c_pack_anchors_n}{#1}{#2}}%
110 % \doglobal\appendetoks
111 %   \pack_anchors_flush{\the\c_pack_anchors_n}{#1}{#2}%
112 % \to \t_pack_anchors_flush
113   \glet\pack_anchors_flush_all\pack_anchors_flush_all_indeed}
114
115\protected\def\pack_anchors_flush#1#2#3%
116  {\doifelseboxincache\v!anchor{#1}
117     {\doifelsereferencefound{\v!layer:\v!anchor:#1}
118        {\ifnum\currentreferencerealpage=\realpageno\relax
119           \setlayer[#2][#3,\c!position=\v!no]{\directboxfromcache\v!anchor{#1}}%
120         \else
121           \donetrue
122         \fi
123         }\donetrue}%
124     \donetrue}%
125
126\protected\def\pack_anchors_flush_all_indeed
127  {\donefalse
128   \expand\t_pack_anchors_flush
129   \ifdone\else
130      \global\t_pack_anchors_flush\emptytoks
131      \glet\pack_anchors_flush_all\relax
132   \fi}
133
134\let\pack_anchors_flush_all\relax
135
136\appendtoks
137    \pack_anchors_flush_all
138\to \everybeforepagebody
139
140\def\pack_anchors_process_finish#1#2#3% brrr: we need to apply offset only once .. a bit messy
141  {\checkpositionoverlays
142   \setbox\b_pack_anchors\box\nextbox
143   \framed % could be a predefined framed but used seldom
144     [\c!offset=\v!overlay,\c!frame=\v!off,#3]
145     {\pack_anchors_register{#1}{#2}%
146      \novrule % hm, not needed as we frame the size (but kind of default)
147        \s!width \wd\b_pack_anchors
148        \s!height\ht\b_pack_anchors
149        \s!depth \dp\b_pack_anchors}%
150   \endgroup}
151
152% \setlayeranchored[text-1][preset=lefttop]{HELLO WORLD} produces a simple (empty) hbox
153% synchronizes per page
154
155\permanent\tolerant\protected\def\setlayeranchored[#1]#*[#S#2]%
156  {\begingroup
157   \ifarguments
158     \dowithnextbox
159       {\endgroup}%
160   \else
161     \dowithnextbox
162       {\checkpositionoverlays
163        \setbox\b_pack_anchors\box\nextbox
164        \dontleavehmode\hpack{\pack_anchors_register{#1}{#2}}%
165        \endgroup}%
166   \fi
167   \hbox}
168
169% collectors
170
171\installcorenamespace{collectorbox}
172\installcorenamespace{collector}
173
174\installcommandhandler \??collector {collector} \??collector
175
176\setupcollector
177  [\c!state=\v!start,
178   \c!x=\zeropoint,
179   \c!y=\zeropoint,
180   \c!offset=\zeropoint,
181   \c!rotation=, % geen 0 !
182   \c!hoffset=\zeropoint,
183   \c!voffset=\zeropoint,
184   \c!location=rb,
185   \c!corner=]
186
187\appendtoks
188   \ifcsname\??collectorbox\currentcollector\endcsname \else
189     \expandafter\newbox\csname\??collectorbox\currentcollector\endcsname
190   \fi
191\to \everydefinecollector
192
193\permanent\protected\def\resetcollector[#1]%
194  {\ifcsname\??collectorbox#1\endcsname
195     \global\setbox\lastnamedcs\emptybox
196   \fi}
197
198\newconditional\c_pack_boxes_collector_valid_box
199
200\mutable\let\b_pack_boxes_collector\scratchbox
201
202\def\pack_boxes_collector_check_box#1%
203  {\edef\currentcollector{#1}%
204   \ifcsname\??collectorbox\currentcollector\endcsname
205     \c_pack_boxes_collector_valid_box\conditionaltrue
206     \expandafter\let\expandafter\b_pack_boxes_collector\lastnamedcs
207   \else
208     \c_pack_boxes_collector_valid_box\conditionalfalse
209     \writestatus{collector}{unknown collector \currentcollector}%
210   \fi}
211
212\permanent\tolerant\protected\def\setcollector[#1]#*[#2]% todo: keep reference point
213  {\bgroup
214   \pack_boxes_collector_check_box{#1}%
215   \ifconditional\c_pack_boxes_collector_valid_box
216     \setupcurrentcollector[#2]%
217     \expandafter\pack_boxes_collector_yes
218   \else
219     \expandafter\pack_boxes_collector_nop
220   \fi}
221
222\def\pack_boxes_collector_yes
223  {\forgetall
224   \dontcomplain
225   \dowithnextboxcs\pack_boxes_collector_finish\hbox}
226
227\let\pack_boxes_collector_nop\egroup
228
229\installcorenamespace{collectorcorners}
230
231\defcsname\??collectorcorners\v!middle\endcsname
232  {\ifdim\d_pack_layers_x_size>\zeropoint
233      \advanceby\d_pack_layers_x_position.5\d_pack_layers_x_size
234    \fi
235    \ifdim\d_pack_layers_y_size>\zeropoint
236      \advanceby\d_pack_layers_y_position.5\d_pack_layers_y_size
237    \fi}
238
239\defcsname\??collectorcorners\v!bottom\endcsname
240  {\ifdim\d_pack_layers_y_size>\zeropoint
241     \advanceby\d_pack_layers_y_position-\d_pack_layers_y_size
242     \d_pack_layers_y_position-\d_pack_layers_y_position
243   \fi}
244
245\defcsname\??collectorcorners\v!right\endcsname
246  {\ifdim\d_pack_layers_x_size>\zeropoint
247     \advanceby\d_pack_layers_x_position-\d_pack_layers_x_size
248     \d_pack_layers_x_position-\d_pack_layers_x_position
249   \fi}
250
251\def\pack_boxes_collector_check_corner#1%
252  {\ifcsname\??collectorcorners#1\endcsname
253     \lastnamedcs
254   \fi}
255
256\def\pack_boxes_collector_finish
257  {\edef\p_collector_rotation{\collectorparameter\c!rotation}%
258   \edef\p_collector_corner  {\collectorparameter\c!corner}%
259   \ifempty\p_collector_rotation \else
260     \setbox\nextbox\hpack
261       {\rotate
262          [\c!location=\v!high,
263           \c!rotation=\p_collector_rotation]
264          {\box\nextbox}}%
265   \fi
266   \d_pack_layers_x_size\wd\b_pack_boxes_collector
267   \d_pack_layers_y_size\htdp\b_pack_boxes_collector
268   \d_pack_layers_x_position\dimexpr\collectorparameter\c!x+\collectorparameter\c!hoffset\relax
269   \d_pack_layers_y_position\dimexpr\collectorparameter\c!y+\collectorparameter\c!voffset\relax
270   \rawprocesscommacommand[\p_collector_corner]\pack_boxes_collector_check_corner
271   \setbox\nextbox\hpack
272     {\alignedbox[\collectorparameter\c!location]\vpack{\box\nextbox}}%
273   \boxmaxdepth\zeropoint % really needed, nice example
274   \global\advanceby\boxhdisplacement\d_pack_layers_x_position
275   \ifdim\boxhdisplacement<\zeropoint
276     \global\setbox\b_pack_boxes_collector\hpack
277       {\kern-\boxhdisplacement
278        \box\b_pack_boxes_collector}%
279   \fi
280   \global\advanceby\boxvdisplacement\d_pack_layers_y_position
281   \ifdim\boxvdisplacement<\zeropoint
282     \global\setbox\b_pack_boxes_collector\hpack
283       {\lower-\boxvdisplacement
284        \box\b_pack_boxes_collector}%
285   \fi
286   \d_pack_layers_x_size\wd\b_pack_boxes_collector
287   \d_pack_layers_y_size\htdp\b_pack_boxes_collector
288   \global\setbox\b_pack_boxes_collector\hpack
289     {\box\b_pack_boxes_collector
290      \kern\dimexpr
291        -\d_pack_layers_x_size
292        +\d_pack_layers_x_position
293         \ifdim\boxhdisplacement<\zeropoint
294           -\boxhdisplacement
295         \fi
296      \relax
297      \lower\d_pack_layers_y_position\hpack
298        {\ifdim\boxvdisplacement<\zeropoint
299           \lower-\boxvdisplacement
300         \fi
301         \box\nextbox}}%
302   % combine height and depth into depth only (later flushed as height)
303   \global\setbox\b_pack_boxes_collector\hpack
304     {\lower\ht\b_pack_boxes_collector\box\b_pack_boxes_collector}%
305   % just to be sure
306   \ifdim\wd\b_pack_boxes_collector<\d_pack_layers_x_size
307     \wd\b_pack_boxes_collector\d_pack_layers_x_size
308   \fi
309   \egroup}
310
311\permanent\protected\def\flushcollector[#1]%
312  {\bgroup
313   \pack_boxes_collector_check_box{#1}%
314   \ifconditional\c_pack_boxes_collector_valid_box
315     \edef\p_collector_state{\collectorparameter\c!state}%
316     \ifx\p_collector_state\v!stop \else
317       \vpack{\hpack{\raise
318         \dp\b_pack_boxes_collector
319         \ifx\p_collector_state\v!repeat\copy\else\box\fi\b_pack_boxes_collector}}%
320     \fi
321   \fi
322   \egroup}
323
324\permanent\protected\def\composedcollector#1% no [], handy as argument
325  {\flushcollector[#1]}
326
327\permanent\tolerant\protected\def\adaptcollector[#1]#*[#S#2]% % a typical case where \global\wd looks better in the code
328  {\begingroup
329   \pack_boxes_collector_check_box{#1}%
330   \ifconditional\c_pack_boxes_collector_valid_box
331     \letcollectorparameter\c!hoffset\zeropoint
332     \letcollectorparameter\c!voffset\zeropoint
333     \setupcurrentcollector[#2]%
334     \global\wd\b_pack_boxes_collector\dimexpr\wd\b_pack_boxes_collector+\collectorparameter\c!hoffset\relax
335     \global\ht\b_pack_boxes_collector\dimexpr\ht\b_pack_boxes_collector+\collectorparameter\c!voffset\relax
336   \fi
337   \endgroup}
338
339%\definecollector[test]
340%\setcollector[test]
341%  [location=rb]
342%  {\externalfigure[koe][frame=on,width=3cm]}
343%\setcollector[test]
344%  [corner={right,bottom},location={left,top}]
345%  {\framed{gans}}
346%\composedcollector{test}
347
348\definecollector
349  [caption]
350
351\permanent\tolerant\protected\def\collectedtext[#1]#*[#S#2]% for captions
352  {\pack_boxes_collector_text[#1][#2]}
353
354\def\pack_boxes_collector_text[#1][#S#2]#3% #3 is mandate so no tolerant here, so still two step
355  {\bgroup
356   \dowithnextbox
357     {\setcollector
358        [caption]
359        {\box\nextbox}%
360      \setcollector
361        [caption][#1]%
362        {\resetdummyparameter\c!style
363         \resetdummyparameter\c!color
364         \getdummyparameters[#2]%
365         \dousestyleparameter{\directdummyparameter\c!style}%
366         \setupinterlinespace
367         \normalexpanded{\framed[\c!foregroundcolor=\directdummyparameter\c!color,\c!foregroundstyle=\directdummyparameter\c!style},\c!frame=\v!overlay,#2]{#3}}%
368      \composedcollector{caption}%
369      \egroup}%
370     \hbox}
371
372% \collectedtext
373%   [corner={right,bottom},location={left,top}]
374%   [background=color,backgroundcolor=white,offset=0pt]
375%   {gans}
376%   {\externalfigure[koe][width=3cm]}
377%
378% \collectedtext
379%   [rotation=90,corner={right,bottom},location={right,top}]
380%   [frame=on,offset=0pt]
381%   {gans}
382%   {\externalfigure[koe][width=3cm]}
383%
384% \collectedtext
385%   [rotation=90,corner={left,bottom},location={left,top}]
386%   [frame=on,offset=0pt]
387%   {gans}
388%   {\externalfigure[koe][width=3cm]}
389
390\installcorenamespace {layeredtext}
391\installcorenamespace {layeredtextlayer}
392\installcorenamespace {layeredtextframed}
393
394\installsimpleframedcommandhandler \??layeredtext {layeredtext} \??layeredtext
395
396\newdimension\d_pack_layeredtexts_width
397\newdimension\d_pack_layeredtexts_height
398
399\definelayer % private
400  [\??layeredtextlayer]
401
402\setuplayer % private
403  [\??layeredtextlayer]
404  [\c!width=\d_pack_layeredtexts_width,
405   \c!height=\d_pack_layeredtexts_height]
406
407\defineframed % private
408  [\??layeredtextframed]
409  [\c!offset=\v!overlay,
410   \c!frame=\v!off,
411   \c!background={\v!foreground,\??layeredtextlayer},
412   \c!width=\d_pack_layeredtexts_width,
413   \c!height=\d_pack_layeredtexts_height]
414
415\setuplayeredtext % public (the attached data, usually small stuff, not the main thing)
416  [\c!frame=\v!overlay,
417   \c!color=,
418   \c!style=,
419   \c!foregroundcolor=\layeredtextparameter\c!color,
420   \c!foregroundstyle=\layeredtextparameter\c!style]
421
422\permanent\tolerant\protected\def\placelayeredtext[#1]#*[#S#2]#*[#S#3]#4% tag layersettings content(framed)settings content
423  {\bgroup
424   \edef\currentlayeredtext{#1}%
425   \checklayeredtextparent % bonus
426   \setupcurrentlayeredtext[#3]%
427   \dowithnextbox
428     {\d_pack_layeredtexts_width \wd\nextbox
429      \d_pack_layeredtexts_height\ht\nextbox
430      \begingroup % preserve \nextbox
431      \setlayer
432        [\??layeredtextlayer]%
433        [#2]%
434        {\fontattributeisset\conditionalfalse
435         \uselayeredtextstyleparameter\c!style
436         \ifconditional\fontattributeisset
437           \setupinterlinespace
438         \fi
439         \inheritedlayeredtextframed{#4}}%
440      \endgroup
441      \placeframed[\??layeredtextframed]{\flushnextbox}%
442      \egroup}%
443     \hbox}
444
445\permanent\protected\def\layeredtext
446  {\placelayeredtext[]}
447
448% \layeredtext
449%   [corner={right,bottom},location={left,top}]
450%   [background=color,backgroundcolor=white,offset=0pt]
451%   {gans}
452%   {\externalfigure[koe][width=3cm]}
453%
454% \layeredtext
455%   [rotation=90,corner={right,bottom},location={right,top}]
456%   [frame=on,offset=0pt]
457%   {gans}
458%   {\externalfigure[koe][width=3cm]}
459%
460% \layeredtext
461%   [rotation=90,corner={left,bottom},location={left,top}]
462%   [frame=on,offset=0pt]
463%   {gans}
464%   {\externalfigure[koe][width=3cm]}
465
466\permanent\tolerant\protected\def\ornamenttext[#1]#*[#S#2]% takes another argument
467  {\bgroup
468   \doifelseassignment{#1}%
469     {\letdummyparameter\c!alternative\v!a
470      \getdummyparameters[#1]%
471      \ifcstok{\directdummyparameter\c!alternative}\v!a
472        \egroup\expandafter\collectedtext
473      \else
474        \egroup\expandafter\layeredtext
475      \fi[#1][#2]}%
476     {\egroup\csname#1\endcsname}}
477
478\permanent\tolerant\protected\def\defineornament[#1]#*[#2]#*[#3]%
479  {\protected\frozen\instance\defcsname#1\endcsname{\ornamenttext[#2][#3]}}
480
481% \defineornament
482%   [affiliation]
483%   [rotation=90,corner={right,bottom},location={right,top},
484%    hoffset=-.25ex]
485%   [frame=on,background=color,backgroundcolor=red,offset=0pt]
486%
487% \ruledhbox{\affiliation{gans}{\externalfigure[koe][width=3cm]}}
488%
489% \defineornament
490%   [affiliation]
491%   [rotation=90,corner={right,bottom},location={right,top},
492%    hoffset=-.25ex,alternative=b]
493%   [frame=on,background=color,backgroundcolor=red,offset=0pt]
494%
495% \ruledhbox{\affiliation{gans}{\externalfigure[koe][width=3cm]}}
496%
497% \defineornament
498%   [affiliation]
499%   [rotation=90,corner={right,bottom},location={left,top},
500%    hoffset=.25ex,voffset=.25ex,alternative=a]
501%   [background=color,style=\ss\tfxx,backgroundcolor=white,offset=0pt]
502%
503% \affiliation{photo}{\externalfigure[molen][width=3cm]}
504%
505% \defineornament
506%   [affiliation]
507%   [rotation=90,corner={right,bottom},location={left,top},
508%    hoffset=.25ex,voffset=.25ex,alternative=b]
509%   [background=color,style=\ss\tfxx,backgroundcolor=white,offset=0pt]
510%
511% \affiliation{drawing}{\externalfigure[hakker][width=3cm]}
512
513\newinteger\c_pack_boxes_bleeds
514
515\installcorenamespace {bleeding}
516
517\installdirectcommandhandler \??bleeding {bleeding} % \??bleeding
518
519\setupbleeding
520  [\c!location=l,
521   \c!stretch=\v!yes,
522   \c!width=3cm,
523   \c!height=3cm,
524   \c!offset=2mm,
525   \c!page=\v!no,
526   \c!voffset=\scratchoffset, % is set to \bleedingparameter\c!offset
527   \c!hoffset=\scratchoffset] % which often saves one resolve
528
529\permanent\def\bleedwidth {\the\hsize} % these are global !
530\permanent\def\bleedheight{\the\vsize} % these are global !
531
532\newconditional\c_pack_boxes_l
533\newconditional\c_pack_boxes_r
534\newconditional\c_pack_boxes_t
535\newconditional\c_pack_boxes_b
536
537\installcorenamespace{bleedinglocation}
538
539\defcsname\??bleedinglocation  t\endcsname{\c_pack_boxes_t\conditionaltrue\scratchhoffset\zeropoint}
540\defcsname\??bleedinglocation  b\endcsname{\c_pack_boxes_b\conditionaltrue\scratchhoffset\zeropoint}
541\defcsname\??bleedinglocation  l\endcsname{\c_pack_boxes_l\conditionaltrue\scratchvoffset\zeropoint}
542\defcsname\??bleedinglocation  r\endcsname{\c_pack_boxes_r\conditionaltrue\scratchvoffset\zeropoint}
543\defcsname\??bleedinglocation bl\endcsname{\c_pack_boxes_l\conditionaltrue\c_pack_boxes_b\conditionaltrue}
544\defcsname\??bleedinglocation lb\endcsname{\c_pack_boxes_l\conditionaltrue\c_pack_boxes_b\conditionaltrue}
545\defcsname\??bleedinglocation br\endcsname{\c_pack_boxes_r\conditionaltrue\c_pack_boxes_b\conditionaltrue}
546\defcsname\??bleedinglocation rb\endcsname{\c_pack_boxes_r\conditionaltrue\c_pack_boxes_b\conditionaltrue}
547\defcsname\??bleedinglocation tl\endcsname{\c_pack_boxes_l\conditionaltrue\c_pack_boxes_t\conditionaltrue}
548\defcsname\??bleedinglocation lt\endcsname{\c_pack_boxes_l\conditionaltrue\c_pack_boxes_t\conditionaltrue}
549\defcsname\??bleedinglocation tr\endcsname{\c_pack_boxes_r\conditionaltrue\c_pack_boxes_t\conditionaltrue}
550\defcsname\??bleedinglocation rt\endcsname{\c_pack_boxes_r\conditionaltrue\c_pack_boxes_t\conditionaltrue}
551
552\mutable\lettonothing\currentbleedposition
553\mutable\lettonothing\currentpageposition
554
555\permanent\tolerant\protected\def\bleed[#1]%
556  {\hbox\bgroup
557   \global\advanceby\c_pack_boxes_bleeds\plusone
558   %
559   \enforced\permanent\xdef\bleedwidth {\the\hsize}%
560   \enforced\permanent\xdef\bleedheight{\the\vsize}%
561   %
562   \edef\currentbleedposition{bleed:\the\c_pack_boxes_bleeds}%
563   \edef\currentpageposition {page:0}% todo: per page
564   %
565   \setupcurrentbleeding[#1]%
566   %
567   \scratchwidth  \bleedingparameter\c!width
568   \scratchheight \bleedingparameter\c!height
569   \scratchoffset \bleedingparameter\c!offset
570   \scratchhoffset\bleedingparameter\c!hoffset
571   \scratchvoffset\bleedingparameter\c!voffset
572   %
573   \c_pack_boxes_l\conditionalfalse % left
574   \c_pack_boxes_r\conditionalfalse % right
575   \c_pack_boxes_t\conditionalfalse % top
576   \c_pack_boxes_b\conditionalfalse % bottom
577   %
578   \csname\??bleedinglocation\bleedingparameter\c!location\endcsname
579   %
580   \ifcstok{\bleedingparameter\c!stretch}\v!yes
581     \donetrue
582   \else
583     \donefalse
584   \fi
585   %
586   \enforced\permanent\xdef\bleedwidth{\the\dimexpr
587     \ifdone
588       \ifconditional\c_pack_boxes_l
589         \scratchwidth+\MPx\currentbleedposition-\MPx\currentpageposition
590       \orelse\ifconditional\c_pack_boxes_r
591         \paperwidth  -\MPx\currentbleedposition+\MPx\currentpageposition % not checked
592       \else
593         \scratchwidth
594       \fi
595     \else
596       \scratchwidth
597     \fi+\scratchhoffset
598   \relax}%
599   \enforced\permanent\xdef\bleedheight{\the\dimexpr
600     \ifdone
601       \ifconditional\c_pack_boxes_t
602         \paperheight  -\MPy\currentbleedposition+\MPy\currentpageposition % not checked
603       \orelse\ifconditional\c_pack_boxes_b
604         \scratchheight+\MPy\currentbleedposition-\MPy\currentpageposition + \MPh\currentbleedposition % not checked (\MPh added)
605       \else
606         \scratchheight
607       \fi
608     \else
609       \scratchheight
610     \fi+\scratchvoffset
611   \relax}%
612   \dowithnextboxcontentcs\pack_boxes_bleed_settings\pack_boxes_bleed_finish\hbox}
613
614\def\pack_boxes_bleed_settings
615  {\hsize\bleedwidth
616   \vsize\bleedheight}
617
618\def\pack_boxes_bleed_finish
619  {\ifcstok{\bleedingparameter\c!page}\v!yes
620     \setbox\nextbox\topskippedbox{\box\nextbox}%
621   \fi
622   \setbox\nextbox\hpack to \scratchwidth
623     {\ifconditional\c_pack_boxes_l\hss\fi
624      \box\nextbox
625      \ifconditional\c_pack_boxes_r\hss\fi}%
626   \ifconditional\c_pack_boxes_b
627     \setbox\nextbox\hpack
628       {\lower\bleedheight\hpack{\raise\scratchheight\box\nextbox}}%
629   \fi
630   \wd\nextbox\scratchwidth
631   \ht\nextbox\scratchheight
632   \dp\nextbox\zeropoint
633   \ifdone
634     \hpos\currentbleedposition{\box\nextbox}%
635   \else
636     \box\nextbox
637   \fi
638   \egroup}
639
640\defineexternalfigure
641  [bleed] % should be \v!bleed
642  [\c!width=\bleedwidth,
643   \c!height=\bleedheight]
644
645% \placefigure[left]{none}
646%   {\bleed[width=5cm,height=3cm,location=lt]{\externalfigure[koe][bleed]}}
647%
648% \input tufte
649%
650% \placefigure[left]{none}
651%   {\bleed[width=5cm,height=3cm,location=l]{\externalfigure[koe][bleed]}}
652%
653% \input tufte
654%
655% \placefigure[right]{none}
656%   {\bleed[width=5cm,height=3cm,location=r]{\externalfigure[koe][bleed]}}
657%
658% \input tufte
659%
660% \placefigure
661%   [top,none]
662%   {} % no caption
663%   {\bleed
664%      [hoffset=-\backspace,
665%       voffset=3mm,
666%       width=0cm,
667%       height=6\lineheight,
668%       page=yes, % correct for topskip
669%       location=lt]
670%      {\externalfigure[koe][bleed][frame=on]}}
671
672% \setlayerframed[layer id][layer settings][framed setting]{data}
673% \setlayerframed[layer id][combined settings]{data}
674
675% tricky: offsets apply to both the layer and the framed; it makes sense to
676% only apply the offset to ...
677
678\permanent\tolerant\protected\def\setlayerframed[#1]#*[#S#2]#*[#S#3]
679  {\ifarguments
680     % error
681   \or
682     \expandafter\pack_layers_set_framed_s
683   \or
684     \expandafter\pack_layers_set_framed_d
685   \or
686     \expandafter\pack_layers_set_framed_t
687   \fi[#1][#2][#3]}
688
689\def\pack_layers_set_framed_s[#1][#2][#3]%
690  {\setlayer[#1][\c!width=\wd\nextbox,\c!height=\ht\nextbox,\c!offset=\zeropoint]%
691     \normalframedwithsettings[\c!location=\v!normal]} % different kind of location
692
693\def\pack_layers_set_framed_d[#1][#2][#3]%
694  {\setlayer[#1][\c!width=\wd\nextbox,\c!height=\ht\nextbox,#2,\c!offset=\zeropoint]%
695     \normalframedwithsettings[\c!location=\v!normal,#2]} % different kind of location
696
697\def\pack_layers_set_framed_t[#1][#2][#3]%
698  {\setlayer[#1][#2]%
699     \normalframedwithsettings[#3]}
700
701\permanent\tolerant\protected\def\setlayertext[#1]#*[#2]#*[#S#3]%
702  {\bgroup
703   \resetdummyparameter\c!align
704   \letdummyparameter  \c!width\hsize
705   \resetdummyparameter\c!color
706   \resetdummyparameter\c!style
707   \getdummyparameters[#3]%
708   \dowithnextboxcontent
709     {\forgetall
710      \hsize\directdummyparameter\c!width
711      \usealignparameter\directdummyparameter
712      \dousestyleparameter{\directdummyparameter\c!style}}
713     {\setlayer[#1][#2]{\strut\dousecolorparameter{\directdummyparameter\c!color}\flushnextbox}% maybe expand the color
714      \egroup}%
715   \vtop}
716
717% \setupbackgrounds
718%   [page]
719%   [background=pagefigures]
720%
721% \definelayer
722%   [pagefigures]
723%   [x=-2mm,
724%    y=-2mm,
725%    width=\paperwidth,
726%    height=\paperheight]
727%
728% \definelayerpreset [lefttop]     [corner={left,top},location={right,bottom}]
729% \definelayerpreset [righttop]    [corner={right,top},location={left,bottom}]
730% \definelayerpreset [leftbottom]  [corner={left,bottom},location={right,top}]
731% \definelayerpreset [rightbottom] [corner={right,bottom},location={left,top}]
732% \definelayerpreset [middle]      [corner=middle,location=middle]
733%
734% \setlayer[pagefigures][preset=lefttop]
735% \setlayer[pagefigures][preset=righttop]
736% \setlayer[pagefigures][preset=leftbottom]
737% \setlayer[pagefigures][preset=rightbottom]
738
739\definelayerpreset
740  [\v!left\v!top]
741  [\c!corner={\v!left,\v!top},\c!location={\v!right,\v!bottom}]
742
743\definelayerpreset
744  [\v!right\v!top]
745  [\c!corner={\v!right,\v!top},\c!location={\v!left,\v!bottom}]
746
747\definelayerpreset
748  [\v!left\v!bottom]
749  [\c!corner={\v!left,\v!bottom},\c!location={\v!right,\v!top}]
750
751\definelayerpreset
752  [\v!right\v!bottom]
753  [\c!corner={\v!right,\v!bottom},\c!location={\v!left,\v!top}]
754
755\definelayerpreset
756  [\v!middle]
757  [\c!corner=\v!middle,\c!location=\v!middle]
758
759\definelayerpreset
760  [\v!middle\v!top]
761  [\c!location=\v!bottom,\c!corner=\v!top,\c!dx=.5\layerwidth]
762
763\definelayerpreset
764  [\v!middle\v!bottom]
765  [\c!location=\v!top,\c!corner=\v!bottom,\c!dx=.5\layerwidth]
766
767\definelayerpreset
768  [\v!middle\v!left]
769  [\c!location=\v!right,\c!corner=\v!left,\c!dy=.5\layerheight]
770
771\definelayerpreset
772  [\v!middle\v!right]
773  [\c!location=\v!left,\c!corner=\v!right,\c!dy=.5\layerheight]
774
775% left and right hanging:
776
777\definelayerpreset
778  [\v!left\v!top\v!left]
779  [\c!location={\v!left,\v!bottom},\c!corner={\v!left,\v!top}]
780
781\definelayerpreset
782  [\v!right\v!top\v!right]
783  [\c!location={\v!right,\v!bottom},\c!corner={\v!right,\v!top}]
784
785\installcorenamespace{alignedboxes}
786
787\permanent\tolerant\protected\def\alignedbox[#1]{\bgroup\serializecommalist[#1]\dowithnextboxcs\pack_boxes_aligned_finish}
788\permanent\tolerant\protected\def\aligned   [#1]{\bgroup\serializecommalist[#1]\dowithnextboxcs\pack_boxes_aligned_finish\hbox}
789
790\def\pack_boxes_aligned_finish
791  {\ifcsname\??alignedboxes\serializedcommalist\endcsname
792     \expandafter\lastnamedcs
793   \else
794     \expandafter\middlebox
795   \fi{\flushnextbox}%
796   \egroup}
797
798\letcsname\??alignedboxes                  \endcsname\middlebox
799\letcsname\??alignedboxes\v!middle         \endcsname\middlebox
800\letcsname\??alignedboxes\v!middle\v!middle\endcsname\middlebox
801\letcsname\??alignedboxes\v!left           \endcsname\leftbox
802\letcsname\??alignedboxes\v!left  \v!top   \endcsname\lefttopbox
803\letcsname\??alignedboxes\v!left  \v!bottom\endcsname\leftbottombox
804\letcsname\??alignedboxes\v!right          \endcsname\rightbox
805\letcsname\??alignedboxes\v!right \v!top   \endcsname\righttopbox
806\letcsname\??alignedboxes\v!right \v!bottom\endcsname\rightbottombox
807\letcsname\??alignedboxes\v!bottom         \endcsname\bottombox
808\letcsname\??alignedboxes\v!bottom\v!left  \endcsname\bottomleftbox
809\letcsname\??alignedboxes\v!bottom\v!right \endcsname\bottomrightbox
810\letcsname\??alignedboxes\v!top            \endcsname\topbox
811\letcsname\??alignedboxes\v!top   \v!left  \endcsname\topleftbox
812\letcsname\??alignedboxes\v!top   \v!right \endcsname\toprightbox
813\letcsname\??alignedboxes\v!line           \endcsname\baselinemiddlebox % \v!grid is taken
814\letcsname\??alignedboxes\v!line  \v!left  \endcsname\baselineleftbox
815\letcsname\??alignedboxes\v!line  \v!middle\endcsname\baselinemiddlebox
816\letcsname\??alignedboxes\v!line  \v!right \endcsname\baselinerightbox
817\letcsname\??alignedboxes                 c\endcsname\middlebox
818\letcsname\??alignedboxes                 l\endcsname\leftbox
819\letcsname\??alignedboxes                 r\endcsname\rightbox
820\letcsname\??alignedboxes                 b\endcsname\bottombox
821\letcsname\??alignedboxes                 t\endcsname\topbox
822\letcsname\??alignedboxes                lt\endcsname\lefttopbox
823\letcsname\??alignedboxes                lb\endcsname\leftbottombox
824\letcsname\??alignedboxes                rt\endcsname\righttopbox
825\letcsname\??alignedboxes                rb\endcsname\rightbottombox
826\letcsname\??alignedboxes                tl\endcsname\topleftbox
827\letcsname\??alignedboxes                bl\endcsname\bottomleftbox
828\letcsname\??alignedboxes                tr\endcsname\toprightbox
829\letcsname\??alignedboxes                br\endcsname\bottomrightbox
830\letcsname\??alignedboxes                 m\endcsname\middlebox
831\letcsname\??alignedboxes                 g\endcsname\baselinemiddlebox
832\letcsname\??alignedboxes                gl\endcsname\baselineleftbox
833\letcsname\??alignedboxes                gc\endcsname\baselinemiddlebox
834\letcsname\??alignedboxes                gr\endcsname\baselinerightbox
835
836% left/right/top/bottomoffset -> dimensions change
837% x/y | method=fixed          -> dimensions don't change
838
839\installcorenamespace{offsetbox}
840
841\installautocommandhandler \??offsetbox {offsetbox} \??offsetbox
842
843\setupoffsetbox
844  [\c!x=\zeropoint,
845   \c!y=\zeropoint,
846   \c!width=\wd\nextbox,
847   \c!height=\ht\nextbox,
848   \c!depth=\dp\nextbox,
849   \c!location=,
850   \c!leftoffset=\zeropoint,
851   \c!rightoffset=\zeropoint,
852   \c!topoffset=\zeropoint,
853   \c!bottomoffset=\zeropoint,
854   \c!method=]
855
856\aliased\let\setupoffset\setupoffsetbox
857
858\permanent\tolerant\protected\def\offsetbox[#S#1]%
859  {\bgroup
860   \pack_boxes_offset_check[#1]%
861   \dowithnextboxcs\pack_boxes_offsetfinish}
862
863\permanent\tolerant\protected\def\offset[#S#1]%
864  {\bgroup
865   \pack_boxes_offset_check[#1]%
866   \dowithnextboxcs\pack_boxes_offsetfinish\hbox}
867
868\newinteger\c_pack_boxes_offset_level
869
870\def\pack_boxes_offset_check
871  {\advanceby\c_pack_boxes_offset_level\plusone
872   \edef\currentoffsetbox{\the\c_pack_boxes_offset_level}%
873   \checkoffsetboxparent
874   \setupcurrentoffsetbox}
875
876\def\pack_boxes_offsetfinish
877  {\donefalse
878   \scratchxposition   \offsetboxparameter\c!x
879   \scratchyposition   \offsetboxparameter\c!y
880   \scratchleftoffset  \offsetboxparameter\c!leftoffset
881   \scratchrightoffset \offsetboxparameter\c!rightoffset
882   \scratchtopoffset   \offsetboxparameter\c!topoffset
883   \scratchbottomoffset\offsetboxparameter\c!bottomoffset
884   \relax % really needed
885   \ifzeropt\scratchleftoffset  \else\donetrue\fi
886   \ifzeropt\scratchrightoffset \else\donetrue\fi
887   \ifzeropt\scratchtopoffset   \else\donetrue\fi
888   \ifzeropt\scratchbottomoffset\else\donetrue\fi
889   \ifdone
890     \ifcstok{\offsetboxparameter\c!method}\v!fixed % new
891       \ifzeropt\scratchleftoffset
892         \ifzeropt\scratchrightoffset \else
893           \scratchxposition-\scratchrightoffset
894           \scratchrightoffset\zeropoint
895         \fi
896       \else
897         \scratchxposition\scratchleftoffset
898         \scratchleftoffset\zeropoint
899       \fi
900       \ifzeropt\scratchtopoffset
901         \ifzeropt\scratchbottomoffset \else
902           \scratchyposition-\scratchbottomoffset
903           \scratchbottomoffset\zeropoint
904         \fi
905       \else
906         \scratchyposition\scratchtopoffset
907         \scratchtopoffset\zeropoint
908       \fi
909       \donefalse
910     \fi
911   \fi
912   \ifdone
913     \setbox\nextbox\vpack
914       {\forgetall % already done
915        \offinterlineskip
916        \kern\scratchtopoffset
917        \hpack
918          {\kern\scratchleftoffset
919           \box\nextbox
920           \kern\scratchrightoffset}%
921        \kern\scratchbottomoffset}%
922     \ht\nextbox\htdp\nextbox
923     \dp\nextbox\zeropoint
924   \fi
925   \scratchwidth \offsetboxparameter\c!width
926   \scratchheight\offsetboxparameter\c!height
927   \scratchdepth \offsetboxparameter\c!depth
928   \edef\p_location{\offsetboxparameter\c!location}%
929   \setbox\nextbox\hpack
930     {\kern\scratchxposition
931      \lower\scratchyposition\hpack
932        {\ifempty\p_location
933           \box\nextbox
934         \else
935           \alignedbox[\p_location]\hpack{\box\nextbox}%
936         \fi}}%
937   \wd\nextbox\scratchwidth
938   \ht\nextbox\scratchheight
939   \dp\nextbox\scratchdepth
940   \box\nextbox
941   \egroup}
942
943%D \starttyping
944%D \framed[offset=overlay]{\offset[leftoffset=1cm]
945%D   {\framed[offset=overlay]{\offset[rightoffset=1cm]
946%D      {\externalfigure[koe][width=1cm]}}}}
947%D
948%D \blank
949%D
950%D \framed[offset=overlay]{\offset[leftoffset=1cm]  {\externalfigure[koe][width=5cm]}} \blank
951%D \framed[offset=overlay]{\offset[rightoffset=1cm] {\externalfigure[koe][width=5cm]}} \blank
952%D \framed[offset=overlay]{\offset[topoffset=1cm]   {\externalfigure[koe][width=5cm]}} \blank
953%D \framed[offset=overlay]{\offset[bottomoffset=1cm]{\externalfigure[koe][width=5cm]}} \blank
954%D \stoptyping
955
956% \useMPlibrary[pre] \setupbackgrounds[page][background=pagegrid]
957%
958% \placefigure[left,none]{}{\offset[leftoffset=1cm]  {\externalfigure[cow][width=3cm]}} \input tufte
959% \placefigure[left,none]{}{\offset[rightoffset=1cm] {\externalfigure[cow][width=3cm]}} \input tufte
960% \placefigure[left,none]{}{\offset[topoffset=1cm]   {\externalfigure[cow][width=3cm]}} \input tufte
961% \placefigure[left,none]{}{\offset[bottomoffset=1cm]{\externalfigure[cow][width=3cm]}} \input tufte
962
963% Some old code:
964%
965% \ltabbed{\romannumerals{3}}{\romannumerals{1}} test \endgraf
966% \ltabbed{\romannumerals{3}}{\romannumerals{2}} test \endgraf
967% \ltabbed{\romannumerals{3}}{\romannumerals{3}} test \endgraf
968%
969% \rtabbed{\romannumerals{3}}{\romannumerals{1}} test \endgraf
970% \rtabbed{\romannumerals{3}}{\romannumerals{2}} test \endgraf
971% \rtabbed{\romannumerals{3}}{\romannumerals{3}} test \endgraf
972%
973% \ctabbed{\romannumerals{3}}{\romannumerals{1}} test \endgraf
974% \ctabbed{\romannumerals{3}}{\romannumerals{2}} test \endgraf
975% \ctabbed{\romannumerals{3}}{\romannumerals{3}} test \endgraf
976
977\def\pack_boxes_tabbed#1#2#3#4%
978  {\dontleavehmode
979   \begingroup
980   \setbox\scratchbox\hpack{#3}%
981   \hpack to \wd\scratchbox{#1#4#2}%
982   \endgroup}
983
984\permanent\protected\def\ltabbed{\pack_boxes_tabbed\relax\hss}
985\permanent\protected\def\rtabbed{\pack_boxes_tabbed\hss  \relax}
986\permanent\protected\def\ctabbed{\pack_boxes_tabbed\hss  \hss}
987
988\aliased\let\mtabbed\ctabbed
989
990% to be documented
991
992\permanent\protected\def\phantombox[#S#1]% == \framed[\c!empty=\v!yes,\c!offset=\v!overlay,#1]{}
993  {\hpack\bgroup
994   \letdummyparameter\c!width \zeropoint
995   \letdummyparameter\c!height\zeropoint
996   \letdummyparameter\c!depth \zeropoint
997   \getdummyparameters[#1]%
998   \setbox\scratchbox\emptyhbox
999   \wd\scratchbox\directdummyparameter\c!width
1000   \ht\scratchbox\directdummyparameter\c!height
1001   \dp\scratchbox\directdummyparameter\c!depth
1002   \box\scratchbox
1003   \egroup}
1004
1005% \backgroundimage{1}{\hsize}{\vsize}{\externalfigure[cow][\c!width=3cm]}
1006
1007% \framed[offset=overlay,width=6cm,height=3cm]{\backgroundimage {1}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}}
1008% \framed[offset=overlay,width=6cm,height=3cm]{\backgroundimage {2}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}}
1009% \framed[offset=overlay,width=6cm,height=3cm]{\backgroundimage {3}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}}
1010
1011% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{1}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}}
1012% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{2}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}}
1013% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{3}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}}
1014% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{1}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}}
1015% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{2}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}}
1016% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{3}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}}
1017%
1018% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{1}{\hsize}{\vsize}{\externalfigure[mill]}}
1019% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{2}{\hsize}{\vsize}{\externalfigure[mill]}}
1020% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{3}{\hsize}{\vsize}{\externalfigure[mill]}}
1021% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{1}{\hsize}{\vsize}{\externalfigure[mill]}}
1022% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{2}{\hsize}{\vsize}{\externalfigure[mill]}}
1023% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{3}{\hsize}{\vsize}{\externalfigure[mill]}}
1024
1025\permanent\protected\def\backgroundimage#1#2#3% repeat hsize vsize
1026  {\bgroup
1027   \forgetall
1028   \scratchcounter#1\relax
1029   \scratchwidth  #2\relax
1030   \scratchheight #3\relax
1031   \dowithnextboxcs\pack_boxes_background_image\hbox}
1032
1033\def\pack_boxes_background_image
1034  {\offinterlineskip
1035   \ifcase\scratchcounter
1036     % just one
1037   \else
1038     \scratchdimen\scratchwidth \divideby\scratchdimen\wd\nextbox\scratchnx\scratchdimen\advanceby\scratchnx\plusone\relax
1039     \scratchdimen\scratchheight\divideby\scratchdimen\ht\nextbox\scratchny\scratchdimen\advanceby\scratchny\plusone\relax
1040     % to be considered: methods
1041     \ifcase\scratchcounter
1042     \or % x and y
1043       \setbox\nextbox\hpack{\localcontrolledrepeat\scratchnx{\copy\nextbox}}%
1044       \setbox\nextbox\vpack{\localcontrolledrepeat\scratchny{\copy\nextbox\endgraf}}%
1045     \or % x
1046       \setbox\nextbox\hpack{\localcontrolledrepeat\scratchnx{\copy\nextbox}}%
1047     \or % y
1048       \setbox\nextbox\vpack{\localcontrolledrepeat\scratchny{\copy\nextbox\endgraf}}%
1049     \fi
1050   \fi
1051   \ifdim\wd\nextbox>\scratchwidth
1052     \setbox\nextbox\hpack to \scratchwidth{\hss\box\nextbox\hss}%
1053     \setbox\nextbox\hpack{\normalexpanded{\clip[\c!width=\the\scratchwidth,\c!height=\the\ht\nextbox]{\box\nextbox}}}%
1054   \fi
1055   \ifdim\ht\nextbox>\scratchheight
1056     \setbox\nextbox\vpack to \scratchheight{\vss\box\nextbox\vss}%
1057     \setbox\nextbox\hpack{\normalexpanded{\clip[\c!width=\the\wd\nextbox,\c!height=\the\scratchheight]{\box\nextbox}}}%
1058   \fi
1059   \box\nextbox
1060   \egroup}
1061
1062\permanent\protected\def\backgroundimagefill#1#2#3% repeat hsize vsize
1063  {\bgroup
1064   \forgetall
1065   \scratchcounter#1\relax
1066   \scratchwidth  #2\relax
1067   \scratchheight #3\relax
1068   \dowithnextboxcs\pack_boxes_background_image_fill\hbox}
1069
1070\def\pack_boxes_background_image_fill
1071  {\offinterlineskip
1072   \setbox\nextbox\hpack\bgroup
1073     \ifdim\scratchwidth>\scratchheight
1074       \scale[\c!width=\the\scratchwidth]{\box\nextbox}%
1075     \else
1076       \scale[\c!height=\the\scratchheight]{\box\nextbox}%
1077     \fi
1078   \egroup
1079   \ifdim\wd\nextbox>\scratchwidth
1080     \setbox\nextbox\hpack to \scratchwidth
1081       {\ifcase\scratchcounter
1082          \hss\box\nextbox\hss
1083        \or
1084          \box\nextbox\hss
1085        \or
1086          \hss\box\nextbox
1087        \else
1088          \hss\box\nextbox\hss
1089        \fi}%
1090     \setbox\nextbox\hpack
1091       {\normalexpanded{\clip[\c!width=\the\scratchwidth,\c!height=\the\ht\nextbox]{\box\nextbox}}}%
1092   \fi
1093   \ifdim\ht\nextbox>\scratchheight
1094     \setbox\nextbox\vpack to \scratchheight
1095       {\ifcase\scratchcounter
1096          \vss\box\nextbox\vss
1097        \or
1098          \box\nextbox\vss
1099        \or
1100          \vss\box\nextbox
1101        \else
1102          \vss\box\nextbox\vss
1103        \fi}%
1104     \setbox\nextbox\hpack
1105       {\normalexpanded{\clip[\c!width=\the\wd\nextbox,\c!height=\the\scratchheight]{\box\nextbox}}}%
1106   \fi
1107   \box\nextbox
1108   \egroup}
1109
1110\permanent\protected\def\overlayimage#1%
1111  {\vpack to \overlayheight\bgroup
1112     \vss
1113     \hpack to \overlaywidth\bgroup
1114        \hss
1115        \externalfigure[#1][\c!factor=\v!min,\c!equalwidth=\overlaywidth,\c!equalheight=\overlayheight]%
1116        \hss
1117     \egroup
1118     \vss
1119  \egroup}
1120
1121\permanent\protected\def\clippedoverlayimage#1%
1122  {\clip
1123     [\c!width=\overlaywidth,\c!height=\overlayheight]
1124     {\overlayimage{#1}}}
1125
1126%D Here is an end December 2021 experimental feature: anchored boxes.
1127
1128\installcorenamespace{boxanchor}
1129\installcorenamespace{boxanchorid}
1130\installcorenamespace{boxanchorbox}
1131\installcorenamespace{boxpreset}
1132\installcorenamespace{boxanchors}
1133
1134\installparameterhandler \??boxanchor {boxanchor}
1135\installsetuphandler     \??boxanchor {boxanchor}
1136
1137\setupboxanchor
1138  [\c!xoffset=\zeropoint,
1139   \c!yoffset=\zeropoint]
1140
1141\newinteger\c_boxes_n_of_anchors
1142
1143\permanent\protected\def\defineanchorbox[#1]%
1144  {\ifcsname\??boxanchorid#1\endcsname
1145     \box\lastnamedcs\emptybox
1146   \else
1147     \global\advanceby\c_boxes_n_of_anchors\plusone
1148     \expandafter\integerdef\csname\??boxanchorid #1\endcsname\c_boxes_n_of_anchors
1149     \expandafter\newbox    \csname\??boxanchorbox#1\endcsname
1150   \fi}
1151
1152\permanent\protected\def\defineanchorboxoverlay[#1]%
1153  {\defineanchorbox[#1:\v!background]%
1154   \defineanchorbox[#1:\v!foreground]%
1155   \defineoverlay[#1:\v!background][\overlayanchorbox{#1:\v!background}]%
1156   \defineoverlay[#1:\v!foreground][\overlayanchorbox{#1:\v!foreground}]}
1157
1158\permanent\def\namedanchorbox#1%
1159  {\begincsname\??boxanchorid#1\endcsname} % no checking
1160
1161\permanent\protected\def\overlayanchorbox#1%
1162  {\begingroup
1163   \scratchcounter\csname\??boxanchorbox#1\endcsname
1164   \ifvoid\scratchcounter\else
1165     \boxsource\scratchcounter\namedanchorbox{#1}%
1166     \wd\scratchcounter\d_overlay_width
1167     \ht\scratchcounter\d_overlay_height
1168     \dp\scratchcounter\d_overlay_depth
1169     \box\scratchcounter
1170   \fi
1171   \endgroup}
1172
1173\mutable\lettonothing\currentanchorbox
1174
1175\permanent\tolerant\protected\def\setanchorbox[#1]#*[#S#2]%
1176  {\begingroup
1177   \dowithnextbox
1178     {\cdef\currentanchorbox{#1}%
1179      \setupboxanchor[#2]%
1180      \scratchcounterone\csname\??boxanchorbox#1\endcsname\relax
1181      \scratchxoffset\boxanchorparameter\c!xoffset\relax
1182      \scratchyoffset\boxanchorparameter\c!yoffset\relax
1183      \boxtarget\nextbox \namedanchorbox {#1}\relax
1184      \boxanchors\nextbox
1185        % target
1186        \numexpr
1187          \ifcsname\??boxpreset\boxanchorparameter\c!target\endcsname
1188            \lastnamedcs
1189          \else
1190            \halfwaytotallistanchorcode
1191          \fi
1192        \relax
1193        % source
1194        \numexpr
1195          \ifcsname\??boxpreset\boxanchorparameter\c!source\endcsname
1196            \lastnamedcs
1197          \else
1198            \halfwaytotallistanchorcode
1199          \fi
1200        \relax
1201      \ifzeropt\scratchxoffset\else
1202         \boxxoffset\nextbox\scratchxoffset
1203      \fi
1204      \ifzeropt\scratchyoffset\else
1205         \boxyoffset\nextbox\scratchyoffset
1206      \fi
1207      \global\setbox\scratchcounterone\hpack\bgroup
1208        \unhbox\scratchcounterone
1209        \kern-\wd\nextbox
1210        \box\nextbox
1211      \egroup
1212      \endgroup}}
1213
1214\expandafter\integerdef\csname\??boxpreset\v!left            \endcsname\leftoriginlistanchorcode
1215\expandafter\integerdef\csname\??boxpreset\v!left,\v!height  \endcsname\leftheightlistanchorcode
1216\expandafter\integerdef\csname\??boxpreset\v!left,\v!top     \endcsname\leftheightlistanchorcode
1217\expandafter\integerdef\csname\??boxpreset\v!left,\v!depth   \endcsname\leftdepthlistanchorcode
1218\expandafter\integerdef\csname\??boxpreset\v!left,\v!bottom  \endcsname\leftdepthlistanchorcode
1219
1220\expandafter\integerdef\csname\??boxpreset\v!right           \endcsname\rightoriginlistanchorcode
1221\expandafter\integerdef\csname\??boxpreset\v!right,\v!height \endcsname\rightheightlistanchorcode
1222\expandafter\integerdef\csname\??boxpreset\v!right,\v!top    \endcsname\rightheightlistanchorcode
1223\expandafter\integerdef\csname\??boxpreset\v!right,\v!depth  \endcsname\rightdepthlistanchorcode
1224\expandafter\integerdef\csname\??boxpreset\v!right,\v!bottom \endcsname\rightdepthlistanchorcode
1225
1226\expandafter\integerdef\csname\??boxpreset\v!line            \endcsname\centeroriginlistanchorcode
1227\expandafter\integerdef\csname\??boxpreset\v!height          \endcsname\centerheightlistanchorcode
1228\expandafter\integerdef\csname\??boxpreset\v!depth           \endcsname\centerdepthlistanchorcode
1229
1230\expandafter\integerdef\csname\??boxpreset\v!middle          \endcsname\halfwaytotallistanchorcode
1231\expandafter\integerdef\csname\??boxpreset\v!middle,\v!height\endcsname\halfwayheightlistanchorcode
1232\expandafter\integerdef\csname\??boxpreset\v!middle,\v!top   \endcsname\halfwayheightlistanchorcode
1233\expandafter\integerdef\csname\??boxpreset\v!middle,\v!depth \endcsname\halfwaydepthlistanchorcode
1234\expandafter\integerdef\csname\??boxpreset\v!middle,\v!bottom\endcsname\halfwaydepthlistanchorcode
1235\expandafter\integerdef\csname\??boxpreset\v!middle,\v!left  \endcsname\halfwayleftlistanchorcode
1236\expandafter\integerdef\csname\??boxpreset\v!middle,\v!right \endcsname\halfwayrightlistanchorcode
1237
1238% Musical timestamp: 2022-02-07 while listening Hypneurotic from The Blurred Horizon (n times);
1239% Jim Matheos with Gavin Harrison; very hypnotic indeed.
1240
1241\permanent\def\boxanchorpresetcode#1%
1242  {\ifcsname\??boxpreset#1\endcsname\lastnamedcs\else\halfwaytotallistanchorcode\fi}
1243
1244\newinteger\registeredboxanchor
1245
1246\installmacrostack\boxanchoringclass
1247
1248\mutable\lettonothing\boxanchoringclass
1249
1250\newinteger\c_anchor_auto_box_class
1251
1252\permanent\protected\def\startboxanchoring[#1]% + == auto
1253  {\push_macro_boxanchoringclass
1254   \iftok{#1}{+}%
1255     \global\advanceby\c_anchor_auto_box_class\plusone
1256     \edef\boxanchoringclass{\the\c_anchor_auto_box_class::}%
1257   \else
1258     \edef\boxanchoringclass{#1}
1259   \fi}
1260
1261\permanent\protected\def\stopboxanchoring
1262  {\pop_macro_boxanchoringclass}
1263
1264\permanent\protected\def\registerboxanchor
1265  {\global\advanceby\registeredboxanchor\minusone}
1266
1267\permanent\protected\def\defineboxanchor[#1]%
1268  {\registerboxanchor
1269   \global\expandafter\integerdef\csname\??boxanchors#1\endcsname\registeredboxanchor}
1270
1271\permanent\protected\def\doifnotanchorbox#1%
1272  {\ifcsname\??boxanchors#1\endcsname
1273     \expandafter\gobbleoneargument
1274   \else
1275     \expandafter\firstofoneargument
1276   \fi}
1277
1278\permanent\def\namedboxanchor#1%
1279  {\normalexpanded{\ifcsname\??boxanchors#1\endcsname\lastnamedcs\orelse\ifchknum#1\or#1\else\zerocount\fi}}
1280
1281\permanent\def\namespacedboxanchor#1%
1282  {boxanchor:\number\namedboxanchor{#1}}
1283
1284\installcorenamespace{boxanchorcontent}
1285
1286% \installparameterhandler \??boxanchorcontent {boxanchorcontent}
1287% \installautosetuphandler \??boxanchorcontent {boxanchorcontent}
1288
1289\installcommandhandler \??boxanchorcontent {boxanchorcontent} \??boxanchorcontent % no real need but let's have a define too
1290
1291\setupboxanchorcontent
1292  [\c!yoffset=\zeropoint,
1293   \c!xoffset=\zeropoint,
1294   \c!width=\zeropoint,
1295   \c!location=\v!height,
1296   \c!corner=\v!depth]
1297
1298\permanent\tolerant\protected\def\setboxanchor[#1]#*[#S#2]#*[#S#3]#*% assumes \defineboxanchor[#1]
1299  {\begingroup
1300   \dowithnextbox
1301     {\ifhastok={#2}%
1302        \setupcurrentboxanchorcontent[#2]%
1303      \else
1304        \cdef\currentboxanchorcontent{#2}%
1305        \setupcurrentboxanchorcontent[#3]%
1306      \fi
1307      \scratchxoffset\boxanchorcontentparameter\c!xoffset
1308      \scratchyoffset\boxanchorcontentparameter\c!yoffset
1309      \scratchcounter\namedboxanchor{#1}%
1310      \registeranchorbox
1311         \scratchcounter
1312         \plusone % order
1313         \hbox
1314            \s!anchors % check order of these:
1315              \boxanchorpresetcode{\boxanchorcontentparameter\c!corner}
1316              \boxanchorpresetcode{\boxanchorcontentparameter\c!location}
1317            \ifzeropt\scratchxoffset\else \s!xoffset \scratchxoffset\fi
1318            \ifzeropt\scratchyoffset\else \s!yoffset \scratchyoffset\fi
1319            \s!target \scratchcounter
1320            {\box\nextbox}%
1321      \endgroup}}
1322
1323%D The name might change:
1324
1325\permanent\protected\def\mathrowanchored #1{\alignmentwrapsource\namedboxanchor{#1}\relax}
1326\permanent\protected\def\mathcellanchored#1{\alignmentcellsource\namedboxanchor{#1}\relax}
1327
1328%permanent\protected\def\mathboxanchored#1#2{#2\Umathsource\namedboxanchor{#1}\relax}
1329
1330\permanent\tolerant\protected\def\mathboxanchored[#1]#:#2#3%
1331  {#3\Umathsource\iftok{#1}{nucleus}#1\fi\namedboxanchor{\boxanchoringclass:#2}\relax}
1332
1333% to be used as:
1334%
1335% \scratchcounter\registeredboxanchor
1336%
1337% \registeranchorbox
1338%   \scratchcounter
1339%   \plusone
1340%   \ruledhbox{...}
1341%
1342% \hbox source \scratchcounter
1343
1344% \negatexlistsigncode
1345% \negateylistsigncode
1346% \negatelistsigncode
1347
1348\protect \endinput
1349