pack-box.mkxl /size: 51 Kb    last modification: 2025-02-21 11:03
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{\collectorparameter\c!x+\collectorparameter\c!hoffset}%
269   \d_pack_layers_y_position{\collectorparameter\c!y+\collectorparameter\c!voffset}%
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{%
291        -\d_pack_layers_x_size
292        +\d_pack_layers_x_position
293         \ifdim\boxhdisplacement<\zeropoint
294           -\boxhdisplacement
295         \fi
296      }%
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{\wd\b_pack_boxes_collector+\collectorparameter\c!hoffset}%
335     \global\ht\b_pack_boxes_collector{\ht\b_pack_boxes_collector+\collectorparameter\c!voffset}%
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%D This more indirect method permits checking if an ornament is defined so that we
482%D can use them as caption location.
483
484\installcorenamespace {ornament}
485
486\permanent\tolerant\protected\def\ornamenttext[#1]#*[#S#2]% takes another argument
487  {\bgroup
488   \doifelseassignment{#1}%
489     {\letdummyparameter\c!alternative\v!a
490      \getdummyparameters[#1]%
491      \ifcstok{\directdummyparameter\c!alternative}\v!a
492        \egroup\expandafter\collectedtext
493      \else
494        \egroup\expandafter\layeredtext
495      \fi[#1][#2]}%
496     {\egroup\csname#1\endcsname}}
497
498\permanent\tolerant\protected\def\defineornament[#1]#*[#2]#*[#3]%
499  {\begingroup
500   \ifhastok={#2}%
501     \letdummyparameter\c!alternative\v!a
502     \letdummyparameter\c!define\v!yes
503     \getdummyparameters[#2]%
504     \ifcstok{\directdummyparameter\c!alternative}\v!a
505       \normalexpanded{\endgroup\pack_box_define_ornament_yes{#1}{\dummyparameter\c!define}}\collectedtext[#2][#3]%
506     \else
507       \normalexpanded{\endgroup\pack_box_define_ornament_yes{#1}{\dummyparameter\c!define}}\layeredtext[#2][#3]%
508     \fi
509   \else
510     \normalexpanded{\endgroup\pack_box_define_ornament_nop{#1}{\dummyparameter\c!define}{#2}}[#3]%
511   \fi}
512
513\protected\def\pack_box_define_ornament_yes#1#2#3[#4][#5]%
514  {\protected\frozen\instance\defcsname\??ornament#1\endcsname{#3[#4][#5]}%
515   \ifcstok{#2}\v!yes
516     \aliased\letcsname#1\expandafter\endcsname\csname\??ornament#1\endcsname
517   \fi}
518
519\protected\def\pack_box_define_ornament_nop#1#2#3[#4]%
520  {\protected\frozen\instance\edefcsname\??ornament#1\endcsname{\noexpand\csname#3\endcsname[#4]}%
521   \ifcstok{#2}\v!yes
522     \aliased\letcsname#1\expandafter\endcsname\csname\??ornament#1\endcsname
523   \fi}
524
525% \defineornament
526%   [affiliation]
527%   [rotation=90,corner={right,bottom},location={right,top},
528%    hoffset=-.25ex]
529%   [frame=on,background=color,backgroundcolor=red,offset=0pt]
530%
531% \ruledhbox{\affiliation{gans}{\externalfigure[koe][width=3cm]}}
532%
533% \defineornament
534%   [affiliation]
535%   [rotation=90,corner={right,bottom},location={right,top},
536%    hoffset=-.25ex,alternative=b]
537%   [frame=on,background=color,backgroundcolor=red,offset=0pt]
538%
539% \ruledhbox{\affiliation{gans}{\externalfigure[koe][width=3cm]}}
540%
541% \defineornament
542%   [affiliation]
543%   [rotation=90,corner={right,bottom},location={left,top},
544%    hoffset=.25ex,voffset=.25ex,alternative=a]
545%   [background=color,style=\ss\tfxx,backgroundcolor=white,offset=0pt]
546%
547% \affiliation{photo}{\externalfigure[molen][width=3cm]}
548%
549% \defineornament
550%   [affiliation]
551%   [rotation=90,corner={right,bottom},location={left,top},
552%    hoffset=.25ex,voffset=.25ex,alternative=b]
553%   [background=color,style=\ss\tfxx,backgroundcolor=white,offset=0pt]
554%
555% \affiliation{drawing}{\externalfigure[hakker][width=3cm]}
556
557\newinteger\c_pack_boxes_bleeds
558
559\installcorenamespace {bleeding}
560
561\installcommandhandler \??bleeding {bleeding} \??bleeding
562
563\setupbleeding
564  [\c!location=l,
565   \c!stretch=\v!yes,
566   \c!width=3cm,
567   \c!height=3cm,
568   \c!offset=2mm,
569   \c!page=\v!no,
570   \c!voffset=\scratchoffset, % is set to \bleedingparameter\c!offset
571   \c!hoffset=\scratchoffset] % which often saves one resolve
572
573\appendtoks
574    \ifcstok{\bleedingparameter\c!define}\v!yes
575        \frozen\instance\protected\edefcsname\currentbleeding\endcsname{\pack_boxes_bleeding{\currentbleeding}}%
576    \fi
577\to \everydefinebleeding
578
579\newdimension \bleedingwidth
580\newdimension \bleedingheight
581
582\permanent\def\bleedwidth {\the\hsize} % these are global !
583\permanent\def\bleedheight{\the\vsize} % these are global !
584
585\newconditional\c_pack_boxes_l % left
586\newconditional\c_pack_boxes_r % right
587\newconditional\c_pack_boxes_t % top
588\newconditional\c_pack_boxes_b % bottom
589
590\installcorenamespace{bleedinglocation}
591
592\defcsname\??bleedinglocation  t\endcsname{\c_pack_boxes_t\conditionaltrue\scratchhoffset\zeropoint}
593\defcsname\??bleedinglocation  b\endcsname{\c_pack_boxes_b\conditionaltrue\scratchhoffset\zeropoint}
594\defcsname\??bleedinglocation  l\endcsname{\c_pack_boxes_l\conditionaltrue\scratchvoffset\zeropoint}
595\defcsname\??bleedinglocation  r\endcsname{\c_pack_boxes_r\conditionaltrue\scratchvoffset\zeropoint}
596\defcsname\??bleedinglocation bl\endcsname{\c_pack_boxes_l\conditionaltrue\c_pack_boxes_b\conditionaltrue}
597\defcsname\??bleedinglocation lb\endcsname{\c_pack_boxes_l\conditionaltrue\c_pack_boxes_b\conditionaltrue}
598\defcsname\??bleedinglocation br\endcsname{\c_pack_boxes_r\conditionaltrue\c_pack_boxes_b\conditionaltrue}
599\defcsname\??bleedinglocation rb\endcsname{\c_pack_boxes_r\conditionaltrue\c_pack_boxes_b\conditionaltrue}
600\defcsname\??bleedinglocation tl\endcsname{\c_pack_boxes_l\conditionaltrue\c_pack_boxes_t\conditionaltrue}
601\defcsname\??bleedinglocation lt\endcsname{\c_pack_boxes_l\conditionaltrue\c_pack_boxes_t\conditionaltrue}
602\defcsname\??bleedinglocation tr\endcsname{\c_pack_boxes_r\conditionaltrue\c_pack_boxes_t\conditionaltrue}
603\defcsname\??bleedinglocation rt\endcsname{\c_pack_boxes_r\conditionaltrue\c_pack_boxes_t\conditionaltrue}
604
605\mutable\lettonothing\currentbleedposition
606\mutable\lettonothing\currentpageposition
607
608% \permanent\tolerant\protected\def\bleed[#1]%
609%   {\hbox\bgroup
610
611\newuserunit \bleedingwidth  bw
612\newuserunit \bleedingheight bh
613\newuserunit \paperbleed     be % bleedingextra
614
615\def\pack_boxes_bleeding_constrain
616  {\beginlocalcontrol
617   \constrained\bleedingwidth \bleedingwidth
618   \constrained\bleedingheight\bleedingheight
619   \endlocalcontrol}
620
621\tolerant\protected\def\pack_boxes_bleeding_preset#1#*[#2]%
622  {\global\advanceby\c_pack_boxes_bleeds\plusone
623   %
624   \retained\bleedingwidth \hsize
625   \retained\bleedingheight\vsize
626   \enforced\permanent\xdef\bleedwidth {\the\bleedingwidth }%
627   \enforced\permanent\xdef\bleedheight{\the\bleedingheight}%
628   %
629   \edef\currentbleedposition{bleed:\the\c_pack_boxes_bleeds}%
630   \edef\currentpageposition {page:0}% todo: per page
631   %
632   \cdef\currentbleeding{#1}%
633   \setupcurrentbleeding[#2]%
634   %
635   \scratchwidth  {\bleedingparameter\c!width}%
636   \scratchheight {\bleedingparameter\c!height}%
637   \scratchoffset {\bleedingparameter\c!offset}%
638   \scratchhoffset{\bleedingparameter\c!hoffset}% \default: \scratchoffset
639   \scratchvoffset{\bleedingparameter\c!voffset}% \default: \scratchoffset
640   %
641   \c_pack_boxes_l\conditionalfalse
642   \c_pack_boxes_r\conditionalfalse
643   \c_pack_boxes_t\conditionalfalse
644   \c_pack_boxes_b\conditionalfalse
645   %
646   \csname\??bleedinglocation\bleedingparameter\c!location\endcsname
647   %
648   \ifcstok{\bleedingparameter\c!stretch}\v!yes
649     \donetrue
650   \else
651     \donefalse
652   \fi
653   %
654   \retained\bleedingwidth{%
655     \ifdone
656       \ifconditional\c_pack_boxes_l
657         \scratchwidth+\jobposx\currentbleedposition-\jobposx\currentpageposition
658       \orelse\ifconditional\c_pack_boxes_r
659         \paperwidth  -\jobposx\currentbleedposition+\jobposx\currentpageposition % not checked
660       \else
661         \scratchwidth
662       \fi
663     \else
664       \scratchwidth
665     \fi+\scratchhoffset
666   }%
667   \retained\bleedingheight{%
668     \ifdone
669       \ifconditional\c_pack_boxes_t
670         \paperheight  -\jobposy\currentbleedposition+\jobposy\currentpageposition % not checked
671       \orelse\ifconditional\c_pack_boxes_b
672         \scratchheight+\jobposy\currentbleedposition-\jobposy\currentpageposition + \jobposh\currentbleedposition % not checked (\MPh added)
673       \else
674         \scratchheight
675       \fi
676     \else
677       \scratchheight
678     \fi+\scratchvoffset
679   }%
680   \enforced\permanent\xdef\bleedwidth {\the\bleedingwidth }%
681   \enforced\permanent\xdef\bleedheight{\the\bleedingheight}}
682
683\tolerant\protected\def\pack_boxes_bleeding#1#*[#2]%
684  {\pack_boxes_bleeding_constrain
685   \hbox\bgroup
686   \pack_boxes_bleeding_preset{#1}[#2]%
687   \dowithnextboxcontentcs\pack_boxes_bleed_settings\pack_boxes_bleed_finish\hbox}
688
689\tolerant\protected\def\startbleeding[#1]#*[#2]%
690  {\pack_boxes_bleeding_constrain
691   \hpack\bgroup
692   \pack_boxes_bleeding_preset{#1}[#2]%
693   \setbox\nextbox\hbox\bgroup
694   \pack_boxes_bleed_settings
695   \ignorespaces}
696
697\tolerant\protected\def\stopbleeding
698  {\removeunwantedspaces
699   \egroup
700   \pack_boxes_bleed_finish}  % ends with egroup
701
702\def\pack_boxes_bleed_settings
703  {\hsize\bleedingwidth
704   \vsize\bleedingheight}
705
706\def\pack_boxes_bleed_finish
707  {\ifcstok{\bleedingparameter\c!page}\v!yes
708     \setbox\nextbox\topskippedbox{\box\nextbox}%
709   \fi
710% todo \boxoffset\nextbox
711   \setbox\nextbox\hpack to \scratchwidth
712     {\ifconditional\c_pack_boxes_l\hss\fi
713      \box\nextbox
714      \ifconditional\c_pack_boxes_r\hss\fi}%
715   \ifconditional\c_pack_boxes_b
716       \boxyoffset\nextbox{-\ht\nextbox+\bleedheight}%
717   \fi
718   \wd\nextbox\scratchwidth
719   \ht\nextbox\scratchheight
720   \dp\nextbox\zeropoint
721   \ifdone
722     \hpos\currentbleedposition{\box\nextbox}%
723   \else
724     \box\nextbox
725   \fi
726   \egroup}
727
728\defineexternalfigure
729  [bleed] % should be \v!bleed
730  [\c!width=\bleedwidth,
731   \c!height=\bleedheight]
732
733\definebleeding
734  [bleed]
735  [\c!define=\v!yes] % \v!bleed
736
737\permanent\protected\def\bleeding[#1]{\pack_boxes_bleeding{#1}}
738
739% \placefigure[left]{none}
740%   {\bleed[width=5cm,height=3cm,location=lt]{\externalfigure[koe][bleed]}}
741%
742% \input tufte
743%
744% \placefigure[left]{none}
745%   {\bleed[width=5cm,height=3cm,location=l]{\externalfigure[koe][bleed]}}
746%
747% \input tufte
748%
749% \placefigure[right]{none}
750%   {\bleed[width=5cm,height=3cm,location=r]{\externalfigure[koe][bleed]}}
751%
752% \input tufte
753%
754% \placefigure
755%   [top,none]
756%   {} % no caption
757%   {\bleed
758%      [hoffset=-\backspace,
759%       voffset=3mm,
760%       width=0cm,
761%       height=6\lineheight,
762%       page=yes, % correct for topskip
763%       location=lt]
764%      {\externalfigure[koe][bleed][frame=on]}}
765
766% \setlayerframed[layer id][layer settings][framed setting]{data}
767% \setlayerframed[layer id][combined settings]{data}
768
769% tricky: offsets apply to both the layer and the framed; it makes sense to
770% only apply the offset to ...
771
772\permanent\tolerant\protected\def\setlayerframed[#1]#*[#S#2]#*[#S#3]
773  {\ifarguments
774     % error
775   \or
776     \expandafter\pack_layers_set_framed_s
777   \or
778     \expandafter\pack_layers_set_framed_d
779   \or
780     \expandafter\pack_layers_set_framed_t
781   \fi[#1][#2][#3]}
782
783\def\pack_layers_set_framed_s[#1][#2][#3]%
784  {\setlayer[#1][\c!width=\wd\nextbox,\c!height=\ht\nextbox,\c!offset=\zeropoint]%
785     \normalframedwithsettings[\c!location=\v!normal]} % different kind of location
786
787\def\pack_layers_set_framed_d[#1][#2][#3]%
788  {\setlayer[#1][\c!width=\wd\nextbox,\c!height=\ht\nextbox,#2,\c!offset=\zeropoint]%
789     \normalframedwithsettings[\c!location=\v!normal,#2]} % different kind of location
790
791\def\pack_layers_set_framed_t[#1][#2][#3]%
792  {\setlayer[#1][#2]%
793     \normalframedwithsettings[#3]}
794
795\permanent\tolerant\protected\def\setlayertext[#1]#*[#2]#*[#S#3]%
796  {\bgroup
797   \resetdummyparameter\c!align
798   \letdummyparameter  \c!width\hsize
799   \resetdummyparameter\c!color
800   \resetdummyparameter\c!style
801   \getdummyparameters[#3]%
802   \dowithnextboxcontent
803     {\forgetall
804      \hsize{\directdummyparameter\c!width}%
805      \usealignparameter\directdummyparameter
806      \dousestyleparameter{\directdummyparameter\c!style}}
807     {\setlayer[#1][#2]{\strut\dousecolorparameter{\directdummyparameter\c!color}\flushnextbox}% maybe expand the color
808      \egroup}%
809   \vtop}
810
811% \setupbackgrounds
812%   [page]
813%   [background=pagefigures]
814%
815% \definelayer
816%   [pagefigures]
817%   [x=-2mm,
818%    y=-2mm,
819%    width=\paperwidth,
820%    height=\paperheight]
821%
822% \definelayerpreset [lefttop]     [corner={left,top},location={right,bottom}]
823% \definelayerpreset [righttop]    [corner={right,top},location={left,bottom}]
824% \definelayerpreset [leftbottom]  [corner={left,bottom},location={right,top}]
825% \definelayerpreset [rightbottom] [corner={right,bottom},location={left,top}]
826% \definelayerpreset [middle]      [corner=middle,location=middle]
827%
828% \setlayer[pagefigures][preset=lefttop]
829% \setlayer[pagefigures][preset=righttop]
830% \setlayer[pagefigures][preset=leftbottom]
831% \setlayer[pagefigures][preset=rightbottom]
832
833\definelayerpreset
834  [\v!left\v!top]
835  [\c!corner={\v!left,\v!top},\c!location={\v!right,\v!bottom}]
836
837\definelayerpreset
838  [\v!right\v!top]
839  [\c!corner={\v!right,\v!top},\c!location={\v!left,\v!bottom}]
840
841\definelayerpreset
842  [\v!left\v!bottom]
843  [\c!corner={\v!left,\v!bottom},\c!location={\v!right,\v!top}]
844
845\definelayerpreset
846  [\v!right\v!bottom]
847  [\c!corner={\v!right,\v!bottom},\c!location={\v!left,\v!top}]
848
849\definelayerpreset
850  [\v!middle]
851  [\c!corner=\v!middle,\c!location=\v!middle]
852
853\definelayerpreset
854  [\v!middle\v!top]
855  [\c!location=\v!bottom,\c!corner=\v!top,\c!dx=.5\layerwidth]
856
857\definelayerpreset
858  [\v!middle\v!bottom]
859  [\c!location=\v!top,\c!corner=\v!bottom,\c!dx=.5\layerwidth]
860
861\definelayerpreset
862  [\v!middle\v!left]
863  [\c!location=\v!right,\c!corner=\v!left,\c!dy=.5\layerheight]
864
865\definelayerpreset
866  [\v!middle\v!right]
867  [\c!location=\v!left,\c!corner=\v!right,\c!dy=.5\layerheight]
868
869% left and right hanging:
870
871\definelayerpreset
872  [\v!left\v!top\v!left]
873  [\c!location={\v!left,\v!bottom},\c!corner={\v!left,\v!top}]
874
875\definelayerpreset
876  [\v!right\v!top\v!right]
877  [\c!location={\v!right,\v!bottom},\c!corner={\v!right,\v!top}]
878
879\installcorenamespace{alignedboxes}
880
881\permanent\tolerant\protected\def\alignedbox[#1]{\bgroup\serializecommalist[#1]\dowithnextboxcs\pack_boxes_aligned_finish}
882\permanent\tolerant\protected\def\aligned   [#1]{\bgroup\serializecommalist[#1]\dowithnextboxcs\pack_boxes_aligned_finish\hbox}
883
884\def\pack_boxes_aligned_finish
885  {\ifcsname\??alignedboxes\serializedcommalist\endcsname
886     \expandafter\lastnamedcs
887   \else
888     \expandafter\middlebox
889   \fi{\flushnextbox}%
890   \egroup}
891
892\letcsname\??alignedboxes                  \endcsname\middlebox
893\letcsname\??alignedboxes\v!middle         \endcsname\middlebox
894\letcsname\??alignedboxes\v!middle\v!middle\endcsname\middlebox
895\letcsname\??alignedboxes\v!left           \endcsname\leftbox
896\letcsname\??alignedboxes\v!left  \v!top   \endcsname\lefttopbox
897\letcsname\??alignedboxes\v!left  \v!bottom\endcsname\leftbottombox
898\letcsname\??alignedboxes\v!right          \endcsname\rightbox
899\letcsname\??alignedboxes\v!right \v!top   \endcsname\righttopbox
900\letcsname\??alignedboxes\v!right \v!bottom\endcsname\rightbottombox
901\letcsname\??alignedboxes\v!bottom         \endcsname\bottombox
902\letcsname\??alignedboxes\v!bottom\v!left  \endcsname\bottomleftbox
903\letcsname\??alignedboxes\v!bottom\v!right \endcsname\bottomrightbox
904\letcsname\??alignedboxes\v!top            \endcsname\topbox
905\letcsname\??alignedboxes\v!top   \v!left  \endcsname\topleftbox
906\letcsname\??alignedboxes\v!top   \v!right \endcsname\toprightbox
907\letcsname\??alignedboxes\v!line           \endcsname\baselinemiddlebox % \v!grid is taken
908\letcsname\??alignedboxes\v!line  \v!left  \endcsname\baselineleftbox
909\letcsname\??alignedboxes\v!line  \v!middle\endcsname\baselinemiddlebox
910\letcsname\??alignedboxes\v!line  \v!right \endcsname\baselinerightbox
911\letcsname\??alignedboxes                 c\endcsname\middlebox
912\letcsname\??alignedboxes                 l\endcsname\leftbox
913\letcsname\??alignedboxes                 r\endcsname\rightbox
914\letcsname\??alignedboxes                 b\endcsname\bottombox
915\letcsname\??alignedboxes                 t\endcsname\topbox
916\letcsname\??alignedboxes                lt\endcsname\lefttopbox
917\letcsname\??alignedboxes                lb\endcsname\leftbottombox
918\letcsname\??alignedboxes                rt\endcsname\righttopbox
919\letcsname\??alignedboxes                rb\endcsname\rightbottombox
920\letcsname\??alignedboxes                tl\endcsname\topleftbox
921\letcsname\??alignedboxes                bl\endcsname\bottomleftbox
922\letcsname\??alignedboxes                tr\endcsname\toprightbox
923\letcsname\??alignedboxes                br\endcsname\bottomrightbox
924\letcsname\??alignedboxes                 m\endcsname\middlebox
925\letcsname\??alignedboxes                 g\endcsname\baselinemiddlebox
926\letcsname\??alignedboxes                gl\endcsname\baselineleftbox
927\letcsname\??alignedboxes                gc\endcsname\baselinemiddlebox
928\letcsname\??alignedboxes                gr\endcsname\baselinerightbox
929
930% left/right/top/bottomoffset -> dimensions change
931% x/y | method=fixed          -> dimensions don't change
932
933\installcorenamespace{offsetbox}
934
935\installautocommandhandler \??offsetbox {offsetbox} \??offsetbox
936
937\setupoffsetbox
938  [\c!x=\zeropoint,
939   \c!y=\zeropoint,
940   \c!width=\wd\nextbox,
941   \c!height=\ht\nextbox,
942   \c!depth=\dp\nextbox,
943   \c!location=,
944   \c!leftoffset=\zeropoint,
945   \c!rightoffset=\zeropoint,
946   \c!topoffset=\zeropoint,
947   \c!bottomoffset=\zeropoint,
948   \c!method=]
949
950\aliased\let\setupoffset\setupoffsetbox
951
952\permanent\tolerant\protected\def\offsetbox[#S#1]%
953  {\bgroup
954   \pack_boxes_offset_check[#1]%
955   \dowithnextboxcs\pack_boxes_offsetfinish}
956
957\permanent\tolerant\protected\def\offset[#S#1]%
958  {\bgroup
959   \pack_boxes_offset_check[#1]%
960   \dowithnextboxcs\pack_boxes_offsetfinish\hbox}
961
962\newinteger\c_pack_boxes_offset_level
963
964\def\pack_boxes_offset_check
965  {\advanceby\c_pack_boxes_offset_level\plusone
966   \edef\currentoffsetbox{\the\c_pack_boxes_offset_level}%
967   \checkoffsetboxparent
968   \setupcurrentoffsetbox}
969
970\def\pack_boxes_offsetfinish
971  {\donefalse
972   \scratchxposition   {\offsetboxparameter\c!x}%
973   \scratchyposition   {\offsetboxparameter\c!y}%
974   \scratchleftoffset  {\offsetboxparameter\c!leftoffset}%
975   \scratchrightoffset {\offsetboxparameter\c!rightoffset}%
976   \scratchtopoffset   {\offsetboxparameter\c!topoffset}%
977   \scratchbottomoffset{\offsetboxparameter\c!bottomoffset}%
978   \relax % really needed
979   \ifzeropt\scratchleftoffset  \else\donetrue\fi
980   \ifzeropt\scratchrightoffset \else\donetrue\fi
981   \ifzeropt\scratchtopoffset   \else\donetrue\fi
982   \ifzeropt\scratchbottomoffset\else\donetrue\fi
983   \ifdone
984     \ifcstok{\offsetboxparameter\c!method}\v!fixed % new
985       \ifzeropt\scratchleftoffset
986         \ifzeropt\scratchrightoffset \else
987           \scratchxposition-\scratchrightoffset
988           \scratchrightoffset\zeropoint
989         \fi
990       \else
991         \scratchxposition\scratchleftoffset
992         \scratchleftoffset\zeropoint
993       \fi
994       \ifzeropt\scratchtopoffset
995         \ifzeropt\scratchbottomoffset \else
996           \scratchyposition-\scratchbottomoffset
997           \scratchbottomoffset\zeropoint
998         \fi
999       \else
1000         \scratchyposition\scratchtopoffset
1001         \scratchtopoffset\zeropoint
1002       \fi
1003       \donefalse
1004     \fi
1005   \fi
1006   \ifdone
1007     \setbox\nextbox\vpack
1008       {\forgetall % already done
1009        \offinterlineskip
1010        \kern\scratchtopoffset
1011        \hpack
1012          {\kern\scratchleftoffset
1013           \box\nextbox
1014           \kern\scratchrightoffset}%
1015        \kern\scratchbottomoffset}%
1016     \ht\nextbox\htdp\nextbox
1017     \dp\nextbox\zeropoint
1018   \fi
1019   \scratchwidth {\offsetboxparameter\c!width}%
1020   \scratchheight{\offsetboxparameter\c!height}%
1021   \scratchdepth {\offsetboxparameter\c!depth}%
1022   \edef\p_location{\offsetboxparameter\c!location}%
1023   \setbox\nextbox\hpack
1024     {\kern\scratchxposition
1025      \lower\scratchyposition\hpack
1026        {\ifempty\p_location
1027           \box\nextbox
1028         \else
1029           \alignedbox[\p_location]\hpack{\box\nextbox}%
1030         \fi}}%
1031   \wd\nextbox\scratchwidth
1032   \ht\nextbox\scratchheight
1033   \dp\nextbox\scratchdepth
1034   \box\nextbox
1035   \egroup}
1036
1037%D \starttyping
1038%D \framed[offset=overlay]{\offset[leftoffset=1cm]
1039%D   {\framed[offset=overlay]{\offset[rightoffset=1cm]
1040%D      {\externalfigure[koe][width=1cm]}}}}
1041%D
1042%D \blank
1043%D
1044%D \framed[offset=overlay]{\offset[leftoffset=1cm]  {\externalfigure[koe][width=5cm]}} \blank
1045%D \framed[offset=overlay]{\offset[rightoffset=1cm] {\externalfigure[koe][width=5cm]}} \blank
1046%D \framed[offset=overlay]{\offset[topoffset=1cm]   {\externalfigure[koe][width=5cm]}} \blank
1047%D \framed[offset=overlay]{\offset[bottomoffset=1cm]{\externalfigure[koe][width=5cm]}} \blank
1048%D \stoptyping
1049
1050% \useMPlibrary[pre] \setupbackgrounds[page][background=pagegrid]
1051%
1052% \placefigure[left,none]{}{\offset[leftoffset=1cm]  {\externalfigure[cow][width=3cm]}} \input tufte
1053% \placefigure[left,none]{}{\offset[rightoffset=1cm] {\externalfigure[cow][width=3cm]}} \input tufte
1054% \placefigure[left,none]{}{\offset[topoffset=1cm]   {\externalfigure[cow][width=3cm]}} \input tufte
1055% \placefigure[left,none]{}{\offset[bottomoffset=1cm]{\externalfigure[cow][width=3cm]}} \input tufte
1056
1057% Some old code:
1058%
1059% \ltabbed{\romannumerals{3}}{\romannumerals{1}} test \endgraf
1060% \ltabbed{\romannumerals{3}}{\romannumerals{2}} test \endgraf
1061% \ltabbed{\romannumerals{3}}{\romannumerals{3}} test \endgraf
1062%
1063% \rtabbed{\romannumerals{3}}{\romannumerals{1}} test \endgraf
1064% \rtabbed{\romannumerals{3}}{\romannumerals{2}} test \endgraf
1065% \rtabbed{\romannumerals{3}}{\romannumerals{3}} test \endgraf
1066%
1067% \ctabbed{\romannumerals{3}}{\romannumerals{1}} test \endgraf
1068% \ctabbed{\romannumerals{3}}{\romannumerals{2}} test \endgraf
1069% \ctabbed{\romannumerals{3}}{\romannumerals{3}} test \endgraf
1070
1071\def\pack_boxes_tabbed#1#2#3#4%
1072  {\dontleavehmode
1073   \begingroup
1074   \setbox\scratchbox\hpack{#3}%
1075   \hpack to \wd\scratchbox{#1#4#2}%
1076   \endgroup}
1077
1078\permanent\protected\def\ltabbed{\pack_boxes_tabbed\relax\hss}
1079\permanent\protected\def\rtabbed{\pack_boxes_tabbed\hss  \relax}
1080\permanent\protected\def\ctabbed{\pack_boxes_tabbed\hss  \hss}
1081
1082\aliased\let\mtabbed\ctabbed
1083
1084% to be documented
1085
1086\permanent\protected\def\phantombox[#S#1]% == \framed[\c!empty=\v!yes,\c!offset=\v!overlay,#1]{}
1087  {\hpack\bgroup
1088   \letdummyparameter\c!width \zeropoint
1089   \letdummyparameter\c!height\zeropoint
1090   \letdummyparameter\c!depth \zeropoint
1091   \getdummyparameters[#1]%
1092   \setbox\scratchbox\emptyhbox
1093   \wd\scratchbox{\directdummyparameter\c!width}%
1094   \ht\scratchbox{\directdummyparameter\c!height}%
1095   \dp\scratchbox{\directdummyparameter\c!depth}%
1096   \box\scratchbox
1097   \egroup}
1098
1099% \backgroundimage{1}{\hsize}{\vsize}{\externalfigure[cow][\c!width=3cm]}
1100
1101% \framed[offset=overlay,width=6cm,height=3cm]{\backgroundimage {1}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}}
1102% \framed[offset=overlay,width=6cm,height=3cm]{\backgroundimage {2}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}}
1103% \framed[offset=overlay,width=6cm,height=3cm]{\backgroundimage {3}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}}
1104
1105% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{1}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}}
1106% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{2}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}}
1107% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{3}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}}
1108% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{1}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}}
1109% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{2}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}}
1110% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{3}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}}
1111%
1112% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{1}{\hsize}{\vsize}{\externalfigure[mill]}}
1113% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{2}{\hsize}{\vsize}{\externalfigure[mill]}}
1114% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{3}{\hsize}{\vsize}{\externalfigure[mill]}}
1115% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{1}{\hsize}{\vsize}{\externalfigure[mill]}}
1116% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{2}{\hsize}{\vsize}{\externalfigure[mill]}}
1117% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{3}{\hsize}{\vsize}{\externalfigure[mill]}}
1118
1119\permanent\protected\def\backgroundimage#1#2#3% repeat hsize vsize
1120  {\bgroup
1121   \forgetall
1122   \scratchcounter#1\relax
1123   \scratchwidth  #2\relax
1124   \scratchheight #3\relax
1125   \dowithnextboxcs\pack_boxes_background_image\hbox}
1126
1127\def\pack_boxes_background_image
1128  {\offinterlineskip
1129   \ifcase\scratchcounter
1130     % just one
1131   \else
1132     \scratchdimen\scratchwidth \divideby\scratchdimen\wd\nextbox\scratchnx\scratchdimen\advanceby\scratchnx\plusone\relax
1133     \scratchdimen\scratchheight\divideby\scratchdimen\ht\nextbox\scratchny\scratchdimen\advanceby\scratchny\plusone\relax
1134     % to be considered: methods
1135     \ifcase\scratchcounter
1136     \or % x and y
1137       \setbox\nextbox\hpack{\localcontrolledrepeat\scratchnx{\copy\nextbox}}%
1138       \setbox\nextbox\vpack{\localcontrolledrepeat\scratchny{\copy\nextbox\endgraf}}%
1139     \or % x
1140       \setbox\nextbox\hpack{\localcontrolledrepeat\scratchnx{\copy\nextbox}}%
1141     \or % y
1142       \setbox\nextbox\vpack{\localcontrolledrepeat\scratchny{\copy\nextbox\endgraf}}%
1143     \fi
1144   \fi
1145   \ifdim\wd\nextbox>\scratchwidth
1146     \setbox\nextbox\hpack to \scratchwidth{\hss\box\nextbox\hss}%
1147     \setbox\nextbox\hpack{\normalexpanded{\clip[\c!width=\the\scratchwidth,\c!height=\the\ht\nextbox]{\box\nextbox}}}%
1148   \fi
1149   \ifdim\ht\nextbox>\scratchheight
1150     \setbox\nextbox\vpack to \scratchheight{\vss\box\nextbox\vss}%
1151     \setbox\nextbox\hpack{\normalexpanded{\clip[\c!width=\the\wd\nextbox,\c!height=\the\scratchheight]{\box\nextbox}}}%
1152   \fi
1153   \box\nextbox
1154   \egroup}
1155
1156\permanent\protected\def\backgroundimagefill#1#2#3% repeat hsize vsize
1157  {\bgroup
1158   \forgetall
1159   \scratchcounter#1\relax
1160   \scratchwidth  #2\relax
1161   \scratchheight #3\relax
1162   \dowithnextboxcs\pack_boxes_background_image_fill\hbox}
1163
1164\def\pack_boxes_background_image_fill
1165  {\offinterlineskip
1166   \setbox\nextbox\hpack\bgroup
1167     \ifdim\scratchwidth>\scratchheight
1168       \scale[\c!width=\the\scratchwidth]{\box\nextbox}%
1169     \else
1170       \scale[\c!height=\the\scratchheight]{\box\nextbox}%
1171     \fi
1172   \egroup
1173   \ifdim\wd\nextbox>\scratchwidth
1174     \setbox\nextbox\hpack to \scratchwidth
1175       {\ifcase\scratchcounter
1176          \hss\box\nextbox\hss
1177        \or
1178          \box\nextbox\hss
1179        \or
1180          \hss\box\nextbox
1181        \else
1182          \hss\box\nextbox\hss
1183        \fi}%
1184     \setbox\nextbox\hpack
1185       {\normalexpanded{\clip[\c!width=\the\scratchwidth,\c!height=\the\ht\nextbox]{\box\nextbox}}}%
1186   \fi
1187   \ifdim\ht\nextbox>\scratchheight
1188     \setbox\nextbox\vpack to \scratchheight
1189       {\ifcase\scratchcounter
1190          \vss\box\nextbox\vss
1191        \or
1192          \box\nextbox\vss
1193        \or
1194          \vss\box\nextbox
1195        \else
1196          \vss\box\nextbox\vss
1197        \fi}%
1198     \setbox\nextbox\hpack
1199       {\normalexpanded{\clip[\c!width=\the\wd\nextbox,\c!height=\the\scratchheight]{\box\nextbox}}}%
1200   \fi
1201   \box\nextbox
1202   \egroup}
1203
1204\permanent\protected\def\overlayimage#1%
1205  {\vpack to \overlayheight\bgroup
1206     \vss
1207     \hpack to \overlaywidth\bgroup
1208        \hss
1209        \externalfigure[#1][\c!factor=\v!min,\c!equalwidth=\overlaywidth,\c!equalheight=\overlayheight]%
1210        \hss
1211     \egroup
1212     \vss
1213  \egroup}
1214
1215\permanent\protected\def\clippedoverlayimage#1%
1216  {\clip
1217     [\c!width=\overlaywidth,\c!height=\overlayheight]
1218     {\overlayimage{#1}}}
1219
1220%D Here is an end December 2021 experimental feature: anchored boxes.
1221
1222\installcorenamespace{boxanchor}
1223\installcorenamespace{boxanchorid}
1224\installcorenamespace{boxanchorbox}
1225\installcorenamespace{boxpreset}
1226\installcorenamespace{boxanchors}
1227
1228\installparameterhandler \??boxanchor {boxanchor}
1229\installsetuphandler     \??boxanchor {boxanchor}
1230
1231\setupboxanchor
1232  [\c!xoffset=\zeropoint,
1233   \c!yoffset=\zeropoint]
1234
1235\newinteger\c_boxes_n_of_anchors
1236
1237\permanent\protected\def\defineanchorbox[#1]%
1238  {\ifcsname\??boxanchorid#1\endcsname
1239     \box\lastnamedcs\emptybox
1240   \else
1241     \global\advanceby\c_boxes_n_of_anchors\plusone
1242     \expandafter\integerdef\csname\??boxanchorid #1\endcsname\c_boxes_n_of_anchors
1243     \expandafter\newbox    \csname\??boxanchorbox#1\endcsname
1244   \fi}
1245
1246\permanent\protected\def\defineanchorboxoverlay[#1]%
1247  {\defineanchorbox[#1:\v!background]%
1248   \defineanchorbox[#1:\v!foreground]%
1249   \defineoverlay[#1:\v!background][\overlayanchorbox{#1:\v!background}]%
1250   \defineoverlay[#1:\v!foreground][\overlayanchorbox{#1:\v!foreground}]}
1251
1252\permanent\def\namedanchorbox#1%
1253  {\begincsname\??boxanchorid#1\endcsname} % no checking
1254
1255\permanent\protected\def\overlayanchorbox#1%
1256  {\begingroup
1257   \scratchcounter\csname\??boxanchorbox#1\endcsname
1258   \ifvoid\scratchcounter\else
1259     \boxsource\scratchcounter\namedanchorbox{#1}%
1260     \wd\scratchcounter\d_overlay_width
1261     \ht\scratchcounter\d_overlay_height
1262     \dp\scratchcounter\d_overlay_depth
1263     \box\scratchcounter
1264   \fi
1265   \endgroup}
1266
1267\mutable\lettonothing\currentanchorbox
1268
1269\permanent\tolerant\protected\def\setanchorbox[#1]#*[#S#2]%
1270  {\begingroup
1271   \dostarttaggednodetail\t!ornament
1272   \dowithnextbox
1273     {\cdef\currentanchorbox{#1}%
1274      \setupboxanchor[#2]%
1275      \scratchcounterone\csname\??boxanchorbox#1\endcsname\relax
1276      \scratchxoffset{\boxanchorparameter\c!xoffset}%
1277      \scratchyoffset{\boxanchorparameter\c!yoffset}%
1278      \boxtarget\nextbox \namedanchorbox {#1}\relax
1279      \boxanchors\nextbox
1280        % target
1281        {%
1282          \ifcsname\??boxpreset\boxanchorparameter\c!target\endcsname
1283            \lastnamedcs
1284          \else
1285            \halfwaytotallistanchorcode
1286          \fi
1287        }%
1288        % source
1289        {%
1290          \ifcsname\??boxpreset\boxanchorparameter\c!source\endcsname
1291            \lastnamedcs
1292          \else
1293            \halfwaytotallistanchorcode
1294          \fi
1295        }%
1296      \ifzeropt\scratchxoffset\else
1297         \boxxoffset\nextbox\scratchxoffset
1298      \fi
1299      \ifzeropt\scratchyoffset\else
1300         \boxyoffset\nextbox\scratchyoffset
1301      \fi
1302      \global\setbox\scratchcounterone\hpack\bgroup
1303        \unhbox\scratchcounterone
1304        \kern-\wd\nextbox
1305        \box\nextbox
1306      \egroup
1307      \dostoptagged
1308      \endgroup}}
1309
1310\expandafter\integerdef\csname\??boxpreset\v!left            \endcsname\leftoriginlistanchorcode
1311\expandafter\integerdef\csname\??boxpreset\v!left,\v!height  \endcsname\leftheightlistanchorcode
1312\expandafter\integerdef\csname\??boxpreset\v!left,\v!top     \endcsname\leftheightlistanchorcode
1313\expandafter\integerdef\csname\??boxpreset\v!left,\v!depth   \endcsname\leftdepthlistanchorcode
1314\expandafter\integerdef\csname\??boxpreset\v!left,\v!bottom  \endcsname\leftdepthlistanchorcode
1315
1316\expandafter\integerdef\csname\??boxpreset\v!right           \endcsname\rightoriginlistanchorcode
1317\expandafter\integerdef\csname\??boxpreset\v!right,\v!height \endcsname\rightheightlistanchorcode
1318\expandafter\integerdef\csname\??boxpreset\v!right,\v!top    \endcsname\rightheightlistanchorcode
1319\expandafter\integerdef\csname\??boxpreset\v!right,\v!depth  \endcsname\rightdepthlistanchorcode
1320\expandafter\integerdef\csname\??boxpreset\v!right,\v!bottom \endcsname\rightdepthlistanchorcode
1321
1322\expandafter\integerdef\csname\??boxpreset\v!line            \endcsname\centeroriginlistanchorcode
1323\expandafter\integerdef\csname\??boxpreset\v!height          \endcsname\centerheightlistanchorcode
1324\expandafter\integerdef\csname\??boxpreset\v!depth           \endcsname\centerdepthlistanchorcode
1325
1326\expandafter\integerdef\csname\??boxpreset\v!middle          \endcsname\halfwaytotallistanchorcode
1327\expandafter\integerdef\csname\??boxpreset\v!middle,\v!height\endcsname\halfwayheightlistanchorcode
1328\expandafter\integerdef\csname\??boxpreset\v!middle,\v!top   \endcsname\halfwayheightlistanchorcode
1329\expandafter\integerdef\csname\??boxpreset\v!middle,\v!depth \endcsname\halfwaydepthlistanchorcode
1330\expandafter\integerdef\csname\??boxpreset\v!middle,\v!bottom\endcsname\halfwaydepthlistanchorcode
1331\expandafter\integerdef\csname\??boxpreset\v!middle,\v!left  \endcsname\halfwayleftlistanchorcode
1332\expandafter\integerdef\csname\??boxpreset\v!middle,\v!right \endcsname\halfwayrightlistanchorcode
1333
1334% Musical timestamp: 2022-02-07 while listening Hypneurotic from The Blurred Horizon (n times);
1335% Jim Matheos with Gavin Harrison; very hypnotic indeed.
1336
1337\permanent\def\boxanchorpresetcode#1%
1338  {\ifcsname\??boxpreset#1\endcsname\lastnamedcs\else\halfwaytotallistanchorcode\fi}
1339
1340\newinteger\registeredboxanchor
1341
1342\installmacrostack\boxanchoringclass
1343
1344\mutable\lettonothing\boxanchoringclass
1345
1346\newinteger\c_anchor_auto_box_class
1347
1348\permanent\protected\def\startboxanchoring[#1]% + == auto
1349  {\push_macro_boxanchoringclass
1350   \iftok{#1}{+}%
1351     \global\advanceby\c_anchor_auto_box_class\plusone
1352     \edef\boxanchoringclass{\the\c_anchor_auto_box_class::}%
1353   \else
1354     \edef\boxanchoringclass{#1}
1355   \fi}
1356
1357\permanent\protected\def\stopboxanchoring
1358  {\pop_macro_boxanchoringclass}
1359
1360\permanent\protected\def\registerboxanchor
1361  {\global\advanceby\registeredboxanchor\minusone}
1362
1363\permanent\protected\def\defineboxanchor[#1]%
1364  {\registerboxanchor
1365   \global\expandafter\integerdef\csname\??boxanchors#1\endcsname\registeredboxanchor}
1366
1367% \permanent\protected\def\doifnotanchorbox#1%
1368%   {\ifcsname\??boxanchors#1\endcsname
1369%      \expandafter\gobbleoneargument
1370%    \else
1371%      \expandafter\firstofoneargument
1372%    \fi}
1373
1374\permanent\protected\def\doifnotanchorbox#1%
1375  {\ifcsname\??boxanchors\boxanchoringclass:#1\endcsname
1376     \expandafter\gobbleoneargument
1377   \orelse\ifcsname\??boxanchors#1\endcsname
1378     \expandafter\gobbleoneargument
1379   \else
1380     \expandafter\firstofoneargument
1381   \fi}
1382
1383% \permanent\def\namedboxanchor#1%
1384%   {\normalexpanded{\ifcsname\??boxanchors#1\endcsname\lastnamedcs\orelse\ifchknum#1\or#1\else\zerocount\fi}}
1385
1386\permanent\def\namedboxanchor#1%
1387  {\normalexpanded{%
1388     \ifcsname\??boxanchors\boxanchoringclass:#1\endcsname
1389       \lastnamedcs
1390     \orelse\ifcsname\??boxanchors#1\endcsname
1391       \lastnamedcs
1392     \orelse\ifchknum#1\or
1393       #1%
1394     \else
1395       \zerocount
1396     \fi
1397    }}
1398
1399\permanent\def\namespacedboxanchor#1% used for positions
1400  {boxanchor:\number\namedboxanchor{#1}}
1401
1402\installcorenamespace{boxanchorcontent}
1403
1404% \installparameterhandler \??boxanchorcontent {boxanchorcontent}
1405% \installautosetuphandler \??boxanchorcontent {boxanchorcontent}
1406
1407\installcommandhandler \??boxanchorcontent {boxanchorcontent} \??boxanchorcontent % no real need but let's have a define too
1408
1409\setupboxanchorcontent
1410  [\c!yoffset=\zeropoint,
1411   \c!xoffset=\zeropoint,
1412   \c!width=\zeropoint,
1413   \c!location=\v!height,
1414   \c!corner=\v!depth]
1415
1416\permanent\tolerant\protected\def\setboxanchor[#1]#*[#S#2]#*[#S#3]#*% assumes \defineboxanchor[#1]
1417  {\begingroup
1418   \dostarttaggednodetail\t!ornament
1419   \dowithnextbox
1420     {\ifhastok={#2}%
1421        \setupcurrentboxanchorcontent[#2]%
1422      \else
1423        \cdef\currentboxanchorcontent{#2}%
1424        \setupcurrentboxanchorcontent[#3]%
1425      \fi
1426      \scratchxoffset{\boxanchorcontentparameter\c!xoffset}%
1427      \scratchyoffset{\boxanchorcontentparameter\c!yoffset}%
1428      \scratchcounter\namedboxanchor{#1}%
1429      \registeranchorbox
1430         \scratchcounter
1431         \plusone % order
1432         \hbox
1433            \s!anchors % check order of these:
1434              \boxanchorpresetcode{\boxanchorcontentparameter\c!corner}
1435              \boxanchorpresetcode{\boxanchorcontentparameter\c!location}
1436            \ifzeropt\scratchxoffset\else \s!xoffset \scratchxoffset\fi
1437            \ifzeropt\scratchyoffset\else \s!yoffset \scratchyoffset\fi
1438            \s!target \scratchcounter
1439            {\box\nextbox}%
1440      \dostoptagged
1441      \endgroup}}
1442
1443%D The name might change:
1444
1445\permanent\protected\def\mathrowanchored #1{\alignmentwrapsource\namedboxanchor{#1}\relax}
1446\permanent\protected\def\mathcellanchored#1{\alignmentcellsource\namedboxanchor{#1}\relax}
1447
1448%permanent\protected\def\mathboxanchored#1#2{#2\Umathsource\namedboxanchor{#1}\relax}
1449
1450\permanent\tolerant\protected\def\mathboxanchored[#1]#:#2#3%
1451  {#3\Umathsource\iftok{#1}{nucleus}#1\fi\namedboxanchor{#2}\relax}
1452
1453% to be used as:
1454%
1455% \scratchcounter\registeredboxanchor
1456%
1457% \registeranchorbox
1458%   \scratchcounter
1459%   \plusone
1460%   \ruledhbox{...}
1461%
1462% \hbox source \scratchcounter
1463
1464% \negatexlistsigncode
1465% \negateylistsigncode
1466% \negatelistsigncode
1467
1468\protect \endinput
1469