pack-lyr.mkxl /size: 28 Kb    last modification: 2021-10-28 13:51
1%D \module
2%D   [       file=pack-lyr,
3%D        version=2000.10.20,
4%D          title=\CONTEXT\ Packaging Macros,
5%D       subtitle=Layers,
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 / Layers}
15
16% todo : first / last / next / +... => page key
17%        test on left/right box when no doublesided option given
18%        use \ifcsname instead of doifvalue
19
20\unprotect
21
22% When being backgrounds layers get the background offset displacement. Should be
23% an option, on by default (compatibility).
24
25%D The layering mechanism implemented here is independent of the output routine, but
26%D future extensions may depend on a more close cooperation.
27%D
28%D First we overload a macro from \type {pack-rul}. From now on we accept a
29%D (optional) argument: the specific layer it will go in. This means that we can
30%D move an overlay from one background to the other using the dimensions of the
31%D parent.
32
33\ifdefined\defineoverlay \else \message{loaded to early} \wait \fi
34
35\pushoverloadmode
36
37\permanent\overloaded\tolerant\protected\def\defineoverlay[#1]#*[#2]#*[#3]% overlay [layer] content
38  {\ifnum\lastarguments=\plusthree
39    %\writestatus{BEWARE}{This (overlay definition) has changed!}% temp
40     \def\pack_framed_define_overlay_indeed##1{\defcsname\??overlay##1\endcsname{\setlayer[#2]{\executedefinedoverlay{##1}{#3}}}}%
41   \else
42     \def\pack_framed_define_overlay_indeed##1{\defcsname\??overlay##1\endcsname{\executedefinedoverlay{##1}{#2}}}%
43   \fi
44   \processcommalist[#1]\pack_framed_define_overlay_indeed}
45
46\popoverloadmode
47
48%D We use the command handler code. The previous, more direct parameter handling was
49%D 25\% faster when no parameters were passed when adding content to a layer.
50%D However, when we pass for instance a preset, the new methos is some 10\% faster
51%D and it happens that in most cases we do pass some parameters. It would be
52%D interesting to see if we can push the preset in between the regular chain but it
53%D could also lead to unwanted side effects when nesting layer placement.
54
55\installcorenamespace{layer}
56\installcorenamespace{layerbox}
57\installcorenamespace{layerpreset}
58\installcorenamespace{layerposition} % brr, unreadable
59
60%D \macros
61%D   {definelayer,setuplayer}
62%D
63%D Each layer gets its own (global) box. This also means that the data that goes
64%D into a layer, is typeset immediately. Each layer automatically gets an associated
65%D overlay, which can be used in any background assignment.
66%D
67%D After a layer is defined, you can change its characteristics.
68
69\installcommandhandler \??layer {layer} \??layer
70
71\setuplayer
72  [\c!state=\v!start,
73  %\c!doublesided=,
74  %\c!preset=,
75  %\c!option=,
76  %\c!corner=,
77  %\c!page=,
78  %\c!rotation=, % geen 0 !
79   \c!direction=\v!normal,
80   \c!position=\v!no,
81   \c!method=\v!overlay,
82   \c!x=\zeropoint,
83   \c!y=\zeropoint,
84   \c!line=0,
85   \c!column=0,
86   \c!width=\wd\nextbox,  % don't change this globally
87   \c!height=\ht\nextbox, % don't change this globally
88   \c!offset=\zeropoint,
89   \c!hoffset=\zeropoint,
90   \c!voffset=\zeropoint,
91   \c!dx=\zeropoint,
92   \c!dy=\zeropoint,
93   \c!location=rb,
94   \c!sx=1,
95   \c!sy=1,
96   \c!region=\layeranchor]
97
98\permanent\def\layeranchor{\currentlayer:\the\realpageno}
99
100\let\p_pack_layers_doublesided\empty
101\let\p_pack_layers_state      \empty
102\let\p_pack_layers_option     \empty
103\let\p_pack_layers_method     \empty
104\let\p_pack_layers_preset     \empty
105\let\p_pack_layers_rotation   \empty
106\let\p_pack_layers_position   \empty
107\let\p_pack_layers_hoffset    \empty
108\let\p_pack_layers_voffset    \empty
109\let\p_pack_layers_offset     \empty
110\let\p_pack_layers_dx         \empty
111\let\p_pack_layers_dy         \empty
112\let\p_pack_layers_sx         \empty
113\let\p_pack_layers_sy         \empty
114\let\p_pack_layers_x          \empty
115\let\p_pack_layers_y          \empty
116\let\p_pack_layers_corner     \empty
117\let\p_pack_layers_location   \empty
118\let\p_pack_layers_line       \empty
119\let\p_pack_layers_column     \empty
120\let\p_pack_layers_width      \empty
121\let\p_pack_layers_height     \empty
122\let\p_pack_layers_direction  \empty
123\let\p_pack_layers_region     \empty
124
125\let\m_pack_layers_page       \empty
126\let\m_pack_layers_target     \empty
127\let\m_pack_layers_region     \empty
128\let\m_pack_layers_anchor     \empty
129
130\newconditional\c_pack_layers_repeated
131\newconditional\c_pack_layers_trace
132\newcount      \c_pack_layers_current_data
133
134\newbox\b_layers \pushoverloadmode \mutable\let\b_layers\b_layers \popoverloadmode
135
136\newdimen\d_pack_layers_x_size
137\newdimen\d_pack_layers_y_size
138\newdimen\d_pack_layers_x_offset
139\newdimen\d_pack_layers_y_offset
140\newdimen\d_pack_layers_x_position
141\newdimen\d_pack_layers_y_position
142
143\newdimen\layerwidth
144\newdimen\layerheight
145
146\mutable\let\lastlayerxpos\!!zeropoint
147\mutable\let\lastlayerypos\!!zeropoint
148\mutable\let\lastlayerwd  \!!zeropoint
149\mutable\let\lastlayerht  \!!zeropoint
150\mutable\let\lastlayerdp  \!!zeropoint
151
152\appendtoks
153    \edef\p_pack_layers_doublesided{\layerparameter\c!doublesided}%
154    \ifx\p_pack_layers_doublesided\v!yes
155        \relateparameterhandlers{layer}{\v!left \currentlayer}{layer}\currentlayer % permits left*
156        \relateparameterhandlers{layer}{\v!right\currentlayer}{layer}\currentlayer % permits right*
157        \pack_layers_preset_box{\v!left \currentlayer}%
158        \pack_layers_preset_box{\v!right\currentlayer}%
159    \fi
160    \pack_layers_preset_box\currentlayer
161    \normalexpanded{\defineoverlay[\currentlayer][\noexpand\composedlayer{\currentlayer}]}%
162\to \everydefinelayer
163
164\def\pack_layers_preset_box#1%
165  {\ifcsname\??layerbox#1\endcsname
166     \resetlayer[#1]%
167   \else
168     \expandafter\newbox\csname\??layerbox#1\endcsname
169   \fi}
170
171%D \macros
172%D  {resetlayer}
173%D
174%D This macro hardly needs an explanation (but is seldom needed anyway).
175
176\def\pack_layers_reset_box#1%
177  {\ifcsname\??layerbox#1\endcsname
178    %\global\setbox\csname\??layerbox#1\endcsname\emptybox
179     \global\setbox\lastnamedcs\emptybox
180   \fi}
181
182\permanent\protected\def\resetlayer[#1]%
183  {\pack_layers_reset_box{#1}%
184   \pack_layers_reset_box{\v!left #1}%
185   \pack_layers_reset_box{\v!right#1}%
186   \pack_layers_reset_box{#1:\the\realpageno}}
187
188%D \macros
189%D   {setlayer}
190%D
191%D Data is moved into a layer with the following macro. When \type {position} is
192%D set, relative positioning is used, with the current point as reference point.
193%D Otherwise the topleft corner is used as reference point.
194%D
195%D \starttyping
196%D \setlayer [identifier] [optional parameters] {data}
197%D \stoptyping
198
199\mutable\let\currentlayerwidth \empty
200\mutable\let\currentlayerheight\empty
201
202\permanent\tolerant\protected\def\setcurrentlayerdimensions[#1]#*[#2]% name left|right
203  {\edef\currentlayerwidth {\thelayerwidth {#2#1}}%
204   \edef\currentlayerheight{\thelayerheight{#2#1}}}
205
206\permanent\def\thelayerwidth #1{\the\ifcsname\??layerbox#1\endcsname\wd\lastnamedcs\else\zeropoint\fi}
207\permanent\def\thelayerheight#1{\the\ifcsname\??layerbox#1\endcsname\ht\lastnamedcs\else\zeropoint\fi}
208
209\permanent\tolerant\protected\def\setlayer[#1]#*[#2]#*[#3]% #4 == box do \fi is ok
210  {\bgroup
211   \nofarguments\lastarguments
212   \checkpositionoverlays % otherwise funny regions
213   \edef\currentlayer{#1}%
214   \edef\p_pack_layers_state{\layerparameter\c!state}%
215   \ifx\p_pack_layers_state\v!stop
216     \dowithnextboxcs\egroup\hbox % no pack ?
217   \orelse\ifnum\nofarguments=\plusthree
218     \edef\m_pack_layers_target{#2}%
219     \pack_layers_set_indeed{#3}%
220   \orelse\ifhastok={#2}%
221     \let\m_pack_layers_target\empty
222     \pack_layers_set_indeed{#2}%
223   \else
224     \edef\m_pack_layers_target{#2}%
225     \pack_layers_set_indeed\empty
226   \fi}
227
228\def\pack_layers_set_indeed#1%
229  {\page_backgrounds_recalculate % brrr
230   \global\advance\c_pack_layers_current_data\plusone
231   \forgetall
232   \dontcomplain
233   \edef\p_pack_layers_option{\layerparameter\c!option}%
234   \ifx\p_pack_layers_option\v!test
235     \settrue\c_pack_layers_trace
236     \traceboxplacementtrue
237   \fi
238   \dowithnextbox{\pack_layers_set_finish{#1}}\hbox}
239
240\def\pack_layers_set_finish#1%
241  {\ifcsname\??layerbox\currentlayer\endcsname % can move up
242     \ifx\m_pack_layers_target\v!even
243       \ifodd\realpageno
244         % discard nextbox
245       \else
246         \let\m_pack_layers_target\v!left
247         \pack_layers_set_content{#1}%
248       \fi
249     \orelse\ifx\m_pack_layers_target\v!odd
250       \ifodd\realpageno
251         \let\m_pack_layers_target\v!right
252         \pack_layers_set_content{#1}%
253       \else
254         % discard nextbox
255       \fi
256     \else
257       \pack_layers_set_content{#1}%
258     \fi
259   \else
260     \writestatus{layer}{unknown layer \currentlayer}%
261   \fi
262   \egroup}
263
264% todo: left/right
265% todo: get position data in one go
266
267\def\pack_layers_set_last_position_yes % target: left|right
268  {% this will become one call
269   \edef\m_pack_layers_anchor{\??layerposition\the\c_pack_layers_current_data}%
270   \edef\m_pack_layers_page  {\MPp\m_pack_layers_anchor}%
271   %edef\m_pack_layers_region{\MPr\m_pack_layers_anchor}% wrong one
272   \edef\m_pack_layers_region{\layerparameter\c!region}%
273   \d_pack_layers_x_position \dimexpr-\MPx\m_pack_layers_region+\MPx\m_pack_layers_anchor\relax
274   \d_pack_layers_y_position \dimexpr \MPy\m_pack_layers_region-\MPy\m_pack_layers_anchor+\MPh\m_pack_layers_region\relax
275   \xdef\lastlayerxpos{\the\d_pack_layers_x_position}%
276   \xdef\lastlayerypos{\the\d_pack_layers_y_position}%
277 % \writestatus{layering}{region: \m_pack_layers_region=>\MPxywhd\m_pack_layers_region}%
278 % \writestatus        {}{anchor: \m_pack_layers_anchor=>\MPxywhd\m_pack_layers_anchor}%
279 % \writestatus        {}{offset: \c!dx,\c!dy          =>\lastlayerxpos,\lastlayerypos}%
280   \global\letlayerparameter\c!state\v!start % needed ?
281   \setbox\b_layers\vpack to \d_pack_layers_y_size
282     {\hpack to \d_pack_layers_x_size
283        {\xypos\m_pack_layers_anchor\hss}%
284      \vss}}
285
286\def\pack_layers_set_last_position_nop
287  {\setbox\b_layers\emptybox
288   \d_pack_layers_x_position\p_pack_layers_sx\dimexpr\p_pack_layers_x\relax
289   \d_pack_layers_y_position\p_pack_layers_sy\dimexpr\p_pack_layers_y\relax
290   \glet\lastlayerxpos\!!zeropoint
291   \glet\lastlayerypos\!!zeropoint
292   \doifinset\v!bottom\p_pack_layers_corner\pack_layers_set_bottom_positions
293   \doifinset\v!right \p_pack_layers_corner\pack_layers_set_right_positions
294   \doifinset\v!middle\p_pack_layers_corner\pack_layers_set_middle_positions
295   \edef\m_pack_layers_page{\layerparameter\c!page}}
296
297\permanent\tolerant\protected\def\definelayerpreset[#1]#*[#2]%
298  {\ifarguments\or
299     \letcsname\??layerpreset#1\endcsname\empty
300   \orelse\ifhastok={#2}%
301     \defcsname\??layerpreset#1\endcsname{\setupcurrentlayer[#2]}%
302   \else
303     \defcsname\??layerpreset#1\endcsname{\csname\??layerpreset#2\endcsname}%
304   \fi}
305
306\mutable\integerdef\b_layers_page\zerocount
307
308\def\pack_layers_set_content#1%
309  {\layerwidth \layerparameter\c!width  % global (local later)
310   \layerheight\layerparameter\c!height % global (local later)
311   \d_pack_layers_x_size\layerwidth
312   \d_pack_layers_y_size\layerheight
313   %
314   \setupcurrentlayer[#1]% preroll
315   %
316   \edef\p_pack_layers_preset   {\layerparameter\c!preset  }%
317   %
318   \ifcsname\??layerpreset\p_pack_layers_preset\endcsname
319     \lastnamedcs
320     \setupcurrentlayer[#1]% postroll
321   \fi
322   %
323   \edef\p_pack_layers_rotation {\layerparameter\c!rotation }%
324   \edef\p_pack_layers_position {\layerparameter\c!position }%
325   \edef\p_pack_layers_hoffset  {\layerparameter\c!hoffset  }%
326   \edef\p_pack_layers_voffset  {\layerparameter\c!voffset  }%
327   \edef\p_pack_layers_offset   {\layerparameter\c!offset   }%
328   \edef\p_pack_layers_dx       {\layerparameter\c!dx       }%
329   \edef\p_pack_layers_dy       {\layerparameter\c!dy       }%
330   \edef\p_pack_layers_sx       {\layerparameter\c!sx       }%
331   \edef\p_pack_layers_sy       {\layerparameter\c!sy       }%
332   \edef\p_pack_layers_x        {\layerparameter\c!x        }%
333   \edef\p_pack_layers_y        {\layerparameter\c!y        }%
334   \edef\p_pack_layers_corner   {\layerparameter\c!corner   }%
335   \edef\p_pack_layers_location {\layerparameter\c!location }%
336   \edef\p_pack_layers_line     {\layerparameter\c!line     }%
337   \edef\p_pack_layers_column   {\layerparameter\c!column   }%
338   \edef\p_pack_layers_width    {\layerparameter\c!width    }% local ones
339   \edef\p_pack_layers_height   {\layerparameter\c!height   }% local ones
340   \edef\p_pack_layers_direction{\layerparameter\c!direction}%
341   %
342   \ifx\p_pack_layers_position\v!overlay
343     \let\p_pack_layers_width   \zeropoint
344     \let\p_pack_layers_height  \zeropoint
345     \let\p_pack_layers_position\v!yes
346   \fi
347   \ifempty\p_pack_layers_rotation \else
348     % use direct call
349     \setbox\nextbox\hpack
350       {\rotate[\c!location=\v!high,\c!rotation=\layerparameter\c!rotation]{\box\nextbox}}%
351   \fi
352   \d_pack_layers_x_offset\p_pack_layers_sx\dimexpr
353     \ifx\p_pack_layers_hoffset\v!max\d_pack_layers_x_size\else\p_pack_layers_hoffset\fi+\p_pack_layers_offset+\p_pack_layers_dx
354   \relax
355   \d_pack_layers_y_offset\p_pack_layers_sy\dimexpr
356     \ifx\p_pack_layers_voffset\v!max\d_pack_layers_y_size\else\p_pack_layers_voffset\fi+\p_pack_layers_offset+\p_pack_layers_dy
357   \relax
358   \ifx\p_pack_layers_position\v!yes
359     \pack_layers_set_last_position_yes
360   \else
361     \pack_layers_set_last_position_nop
362   \fi
363   %
364   \ifempty\m_pack_layers_page \else % is expanded
365     \edef\m_pack_layers_page{:\m_pack_layers_page}%
366     \ifcsname\??layerbox\m_pack_layers_target\currentlayer\m_pack_layers_page\endcsname \else
367       \expandafter\newbox\csname\??layerbox\m_pack_layers_target\currentlayer\m_pack_layers_page\endcsname
368     \fi
369   \fi
370   \integerdef\b_layers_page\csname\??layerbox\m_pack_layers_target\currentlayer\m_pack_layers_page\endcsname
371   \ifvoid\b_layers_page
372     \gsetboxllx\b_layers_page\zeropoint
373     \gsetboxlly\b_layers_page\zeropoint
374   \fi
375   \global\setbox\b_layers_page\vpack %to \layerparameter\c!height % new, otherwise no negative y possible
376     {\offinterlineskip
377      \ifvoid\b_layers_page
378        \scratchwidth \zeropoint
379        \scratchheight\zeropoint
380      \else
381        \scratchwidth \wd\b_layers_page
382        \scratchheight\ht\b_layers_page
383        \ht\b_layers_page\zeropoint
384        \dp\b_layers_page\zeropoint
385        \wd\b_layers_page\zeropoint
386        \ifx\p_pack_layers_direction\v!reverse\else
387          \box\b_layers_page
388        \fi
389      \fi
390      % don't move
391      \xdef\lastlayerwd{\the\wd\nextbox}%
392      \xdef\lastlayerht{\the\ht\nextbox}% % not entirely ok when grid !
393      \xdef\lastlayerdp{\the\dp\nextbox}% % not entirely ok when grid !
394      % this code
395      \ifx\p_pack_layers_location\v!grid
396        \ht\nextbox\strutheight
397        \dp\nextbox\strutdepth
398      \else
399        \setbox\nextbox\hpack
400          {\alignedbox[\p_pack_layers_location]\vpack{\box\nextbox}}%
401      \fi
402      \ifnum\p_pack_layers_line=\zerocount\else % no \ifcase, can be negative
403        \advance\d_pack_layers_y_position\dimexpr\p_pack_layers_line\lineheight+\topskip-\lineheight-\ht\nextbox\relax
404      \fi
405      \ifnum\p_pack_layers_column=\zerocount\else % no \ifcase, can be negative
406        \advance\d_pack_layers_x_position\layoutcolumnoffset\p_pack_layers_column\relax
407      \fi
408      \ifx\p_pack_layers_location\v!grid
409        \setbox\nextbox\hpack
410          {\alignedbox[rb]\vpack{\box\nextbox}}%
411      \fi
412      % ll registration
413      \scratchdimen\dimexpr\d_pack_layers_x_position+\d_pack_layers_x_offset\relax
414      \ifdim\scratchdimen<\getboxllx\b_layers_page
415        \gsetboxllx\b_layers_page\scratchdimen
416      \fi
417      \advance\scratchdimen\wd\nextbox
418      \wd\nextbox\ifdim\scratchdimen>\scratchwidth \scratchdimen \else \scratchwidth \fi
419      \scratchdimen\dimexpr\d_pack_layers_y_position+\d_pack_layers_y_offset\relax
420      \ifdim\scratchdimen<\getboxlly\b_layers_page
421        \gsetboxlly\b_layers_page\scratchdimen
422      \fi
423      % ll compensation
424      \advance\scratchdimen\dimexpr\ht\nextbox+\dp\nextbox\relax
425      \ht\nextbox\ifdim\scratchdimen>\scratchheight \scratchdimen \else \scratchheight \fi
426      \dp\nextbox\zeropoint
427      % placement
428      \hsize\p_pack_layers_width
429      \vpack to \p_pack_layers_height \bgroup
430        \smashbox\nextbox
431        \vskip\dimexpr\d_pack_layers_y_position+\d_pack_layers_y_offset\relax
432        \hskip\dimexpr\d_pack_layers_x_position+\d_pack_layers_x_offset\relax
433        % or maybe instead of the \vskip
434        % \raise-\dimexpr\d_pack_layers_y_position+\d_pack_layers_y_offset\relax
435        \box\nextbox
436        \ifvoid\b_layers_page
437          % already flushed
438        \else
439          % the reverse case % check !
440          \vskip-\dimexpr\d_pack_layers_y_position+\d_pack_layers_y_offset\relax
441          \box\b_layers_page
442        \fi
443      \egroup}%
444   % when position is true, the layerbox holds the compensation and needs
445   % to be placed; never change this !
446   \ifvoid\b_layers \else
447     \box\b_layers
448   \fi}
449
450\def\pack_layers_set_bottom_positions
451  {\ifnum\p_pack_layers_line=\zerocount\else % can be < 0
452     \edef\p_pack_layers_line{\the\numexpr-\p_pack_layers_line+\layoutlines+\plusone\relax}% use counter instead ?
453   \fi
454   \ifdim\d_pack_layers_y_size>\zeropoint
455     \advance\d_pack_layers_y_position-\d_pack_layers_y_size
456     \d_pack_layers_y_position-\d_pack_layers_y_position
457     \d_pack_layers_y_offset-\d_pack_layers_y_offset
458   \fi}
459
460\def\pack_layers_set_right_positions
461  {\ifnum\p_pack_layers_column=\zerocount\else % can be < 0
462     \edef\p_pack_layers_column{\the\numexpr-\layerparameter\c!column+\layoutcolumns+\plusone\relax}% use counter instead ?
463   \fi
464   \ifdim\d_pack_layers_x_size>\zeropoint
465     \advance\d_pack_layers_x_position-\d_pack_layers_x_size
466     \d_pack_layers_x_position-\d_pack_layers_x_position
467     \d_pack_layers_x_offset-\d_pack_layers_x_offset
468   \fi}
469
470\def\pack_layers_set_middle_positions
471  {\ifdim\d_pack_layers_x_size>\zeropoint \advance\d_pack_layers_x_position.5\d_pack_layers_x_size \fi
472   \ifdim\d_pack_layers_y_size>\zeropoint \advance\d_pack_layers_y_position.5\d_pack_layers_y_size \fi}
473
474%D Given the task to be accomplished, the previous macro is not even that
475%D complicated. It mainly comes down to skipping to the right place and placing a
476%D box on top of or below the existing content. In the case of position tracking,
477%D another reference point is chosen.
478
479%D \macros
480%D  {doifelselayerdata}
481
482\permanent\def\doifelselayerdata#1%
483  {\ifcsname\??layerbox#1\endcsname
484    %\ifvoid\csname\??layerbox#1\endcsname
485     \ifvoid\lastnamedcs
486       \doubleexpandafter\secondoftwoarguments
487     \else
488       \doubleexpandafter\firstoftwoarguments
489     \fi
490   \else
491     \expandafter\secondoftwoarguments
492   \fi}
493
494\aliased\let\doiflayerdataelse\doifelselayerdata
495
496%D \macros
497%D  {flushlayer}
498%D
499%D When we flush a layer, we flush both the main one and the page dependent one
500%D (when defined). This feature is more efficient in \ETEX\ since there testing for
501%D an undefined macro does not takes hash space.
502
503% todo: setups before flush, handy hook
504
505\permanent\protected\def\flushlayer[#1]% quite core, so optimized (todo: check for void)
506  {\begingroup
507   \forgetall
508   \edef\currentlayer{#1}%
509   \edef\p_pack_layers_state{\layerparameter\c!state}%
510   \ifx\p_pack_layers_state\v!stop
511     % nothing
512   \orelse\ifx\p_pack_layers_state\v!next
513     \global\letlayerparameter\c!state\v!start  % dangerous, stack-built-up
514   \orelse\ifx\p_pack_layers_state\v!continue
515     \global\letlayerparameter\c!state\v!repeat % dangerous, stack-built-up
516   \else
517     \edef\p_pack_layers_doublesided{\layerparameter\c!doublesided}%
518     \ifx\p_pack_layers_doublesided\v!yes
519       \ifcsname\??layerbox#1\endcsname
520         % we can make a dedicated one for this
521         \doifbothsidesoverruled
522           {\pack_layers_flush_double\v!left }%
523           {\pack_layers_flush_double\v!right}%
524           {\pack_layers_flush_double\v!left }%
525       \else
526         \pack_layers_flush_single
527       \fi
528     \else
529       \pack_layers_flush_single
530     \fi
531   \fi
532   \endgroup}
533
534% optimized
535
536\mutable\integerdef\b_layer_one\zerocount
537\mutable\integerdef\b_layer_two\zerocount
538
539\def\pack_layers_flush_single
540  {\ifcsname\??layerbox\currentlayer\endcsname
541     \ifvoid\lastnamedcs
542       \ifcsname\??layerbox\currentlayer:\the\realpageno\endcsname
543         \ifvoid\lastnamedcs\else
544           \chardef\b_layer_two\lastnamedcs
545           \pack_layers_flush_indeed\zerocount{\currentlayer:\the\realpageno}\b_layer_two
546         \fi
547       \fi
548     \else
549       \chardef\b_layer_one\lastnamedcs % will be \integerdef
550       \ifcsname\??layerbox\currentlayer:\the\realpageno\endcsname
551         \ifvoid\lastnamedcs\else
552           \chardef\b_layer_two\lastnamedcs % will be \integerdef
553           \startoverlay
554             {\pack_layers_flush_indeed\plusone   \currentlayer                 \b_layer_one}%
555             {\pack_layers_flush_indeed\zerocount{\currentlayer:\the\realpageno}\b_layer_two}%
556           \stopoverlay
557         \fi
558       \else
559         \pack_layers_flush_indeed\plusone\currentlayer\b_layer_one
560       \fi
561     \fi
562   \orelse\ifcsname\??layerbox\currentlayer:\the\realpageno\endcsname
563     \ifvoid\lastnamedcs
564        % nothing
565     \else
566       \chardef\b_layer_two\lastnamedcs
567       \pack_layers_flush_indeed\zerocount{\currentlayer:\the\realpageno}\b_layer_two
568     \fi
569   \fi}
570
571% less optimized:
572
573\def\pack_layers_flush_double#1%
574  {\startoverlay
575     {\ifcsname\??layerbox\currentlayer\endcsname
576        \ifvoid\lastnamedcs\else \chardef\b_layer_two\lastnamedcs
577          \pack_layers_flush_indeed\plusone\currentlayer\b_layer_two
578        \fi
579      \fi}%
580     {\ifcsname\??layerbox\currentlayer:\the\realpageno\endcsname
581        \ifvoid\lastnamedcs\else \chardef\b_layer_two\lastnamedcs
582          \pack_layers_flush_indeed\zerocount{\currentlayer:\the\realpageno}\b_layer_two
583        \fi
584      \fi}%
585     {\ifcsname\??layerbox#1\currentlayer\endcsname
586        \ifvoid\lastnamedcs\else \chardef\b_layer_two\lastnamedcs
587          \pack_layers_flush_indeed\plusone{#1\currentlayer}\b_layer_two
588        \fi
589      \fi}%
590     {\ifcsname\??layerbox#1\currentlayer:\the\realpageno\endcsname
591        \ifvoid\lastnamedcs\else \chardef\b_layer_two\lastnamedcs
592          \pack_layers_flush_indeed\zerocount{#1\currentlayer:\the\realpageno}\b_layer_two
593        \fi
594      \fi}%
595   \stopoverlay}
596
597\let\pack_layers_top_fill   \relax
598\let\pack_layers_bottom_fill\vss
599
600\def\pack_layers_flush_indeed#1#2#3%
601  {\begingroup % already grouped
602   \offinterlineskip
603   \edef\p_pack_layers_preset{\layerparameter\c!preset}%
604   \ifcsname\??layerpreset\p_pack_layers_preset\endcsname
605     \lastnamedcs
606   \fi
607   \edef\p_pack_layers_method{\layerparameter\c!method}%
608   \edef\p_pack_layers_option{\layerparameter\c!option}%
609   \ifx\p_pack_layers_option\v!test
610     \settrue\c_pack_layers_trace
611     \traceboxplacementtrue
612   \fi
613   \ifcase#1\relax
614     \setfalse\c_pack_layers_repeated
615   \else
616     \edef\p_pack_layers_position{\layerparameter\c!position}%
617     \ifx\p_pack_layers_position\v!yes
618       \setfalse\c_pack_layers_repeated
619     \else
620       \edef\p_pack_layers_repeat{\layerparameter\c!repeat}%
621       \ifx\p_pack_layers_repeat\v!yes
622         \settrue\c_pack_layers_repeated
623       \orelse\ifx\p_pack_layers_state\v!repeat
624         \settrue\c_pack_layers_repeated
625       \else
626         \setfalse\c_pack_layers_repeated
627       \fi
628     \fi
629   \fi
630   %chardef\b_layers\csname\??layerbox#2\endcsname % trick
631   \let\b_layers#3%
632   % we need to copy in order to retain the negative offsets for a next
633   % stage of additions, i.e. llx/lly accumulate in repeat mode and the
634   % compensation may differ each flush depending on added content
635   \setbox\nextbox
636     \ifx\p_pack_layers_method\v!fit
637       \pack_layers_positioned_box_yes
638     \else
639       \pack_layers_positioned_box_nop
640     \fi
641   % todo: method=offset => overlayoffset right/down (handy for backgrounds with offset)
642   \doifelseoverlay{#2}%
643     {\setlayoutcomponentattribute{\v!layer:#2}}%
644     \resetlayoutcomponentattribute
645   % we have conflicting demands: some mechanisms want ll anchoring .. I need to figure this out
646   % and maybe we will have 'origin=bottom' or so
647   \setbox\nextbox
648   \ifx\p_pack_layers_option\v!test \ruledvbox \else \vpack \fi \ifx\p_pack_layers_method\v!overlay to \d_overlay_height \fi \layoutcomponentboxattribute
649     {\pack_layers_top_fill
650%
651%       \hpack \ifx\p_pack_layers_method\v!overlay to \d_overlay_width \fi
652%         {\box\nextbox
653%          \hss}%
654%
655      \ifx\p_pack_layers_method\v!overlay \wd\nextbox\d_overlay_width\fi
656      \box\nextbox
657%
658      \pack_layers_bottom_fill}%
659   % \edef\currentlayer{#2}% :\the\realpageno}% local .. check \anchor
660   % \edef\p_pack_layers_position{\layerparameter\c!position}% local
661   \ifx\p_pack_layers_position\v!yes
662     \edef\p_pack_layers_region{\layerparameter\c!region}%
663     \ifempty\p_pack_layers_region\else
664       \anch_mark_tagged_box\nextbox\p_pack_layers_region % was \layeranchor
665     \fi
666   \fi
667   \box\nextbox
668   %
669   \ifconditional\c_pack_layers_repeated\else
670     \gsetboxllx\b_layers\zeropoint
671     \gsetboxlly\b_layers\zeropoint
672   \fi
673   \endgroup}
674
675\def\pack_layers_positioned_box_yes
676  {\vpack
677     {\vskip-\getboxlly\b_layers
678      \hskip-\getboxllx\b_layers
679      \hsize-\dimexpr\getboxllx\b_layers-\wd\b_layers\relax
680      \ifconditional\c_pack_layers_repeated\copy\else\box\fi\b_layers}}
681
682\def\pack_layers_positioned_box_nop
683  {\ifconditional\c_pack_layers_repeated\copy\else\box\fi\b_layers}
684
685% \definelayer[test][method=fit] \setupcolors[state=start,option=test]
686%
687% \framed[framecolor=red,offset=overlay]{\setlayer[test]{aa}\setlayer[test][x=10pt]{g}\flushlayer[test]}
688% \framed[framecolor=red,offset=overlay]{\setlayer[test]{aa}\setlayer[test][x=-10pt]{bb}\flushlayer[test]}
689% \framed[framecolor=red,offset=overlay]{\setlayer[test][x=-20pt]{cccccc}\flushlayer[test]}
690% \framed[framecolor=red,offset=overlay]{\setlayer[test]{dd}\setlayer[test][x=-20pt,y=-3pt]{eeeeee}\flushlayer[test]}
691
692%D \macros
693%D  {composedlayer,placelayer,tightlayer}
694%D
695%D This is a handy shortcut, which saves a couple of braces when we use it as
696%D parameter. This name also suits better to other layering commands.
697
698\permanent\protected\def\composedlayer#1{\flushlayer[#1]}
699
700\permanent\protected\def\tightlayer[#1]%
701  {\hpack
702     {\def\currentlayer{#1}% todo: left/right
703      \setbox\nextbox\emptybox
704      \d_overlay_width \layerparameter\c!width
705      \d_overlay_height\layerparameter\c!height
706      \composedlayer{#1}}}
707
708\aliased\let\placelayer\flushlayer
709
710%D \macros
711%D  {setMPlayer}
712%D
713%D The following layer macro uses the positions that are registered by \METAPOST.
714%D
715%D \starttyping
716%D \definelayer[test]
717%D
718%D \setMPlayer [test] [somepos-1] {Whatever we want here!}
719%D \setMPlayer [test] [somepos-2] {Whatever we need there!}
720%D \setMPlayer [test] [somepos-3] {\externalfigure[cow.mps][width=2cm]}
721%D
722%D \startuseMPgraphic{oeps}
723%D   draw fullcircle scaled 10cm withcolor red ;
724%D   register ("somepos-1",2cm,3cm,center currentpicture) ;
725%D   register ("somepos-2",8cm,5cm,(-1cm,-2cm)) ;
726%D   register ("somepos-3",0cm,0cm,(-2cm,2cm)) ;
727%D \stopuseMPgraphic
728%D
729%D \getMPlayer[test]{\useMPgraphic{oeps}}
730%D \stoptyping
731%D
732%D The last line is equivalent to
733%D
734%D \starttyping
735%D \framed
736%D   [background={foreground,test},offset=overlay]
737%D   {\useMPgraphic{oeps}}
738%D \stoptyping
739
740\mutable\def\MPlayerwidth {\hsize}
741\mutable\def\MPlayerheight{\vsize}
742
743\permanent\tolerant\protected\def\setMPlayer[#1]#*[#2]#*[#3]%
744  {\edef\MPlayerwidth {\MPw{#2}}%
745   \edef\MPlayerheight{\MPh{#2}}%
746   \setlayer[#1][\c!x=\MPx{#2},\c!y=\MPy{#2},\c!position=\v!no,#3]}
747
748\permanent\tolerant\protected\def\getMPlayer[#1]#*[#2]%
749  {\framed[\c!background={\v!foreground,#1},\c!frame=\v!off,\c!offset=\v!overlay,#2]} % takes argument
750
751%D Watch out, a redefinition:
752
753\ifdefined\settextpagecontent \else
754    \writestatus\m!system{error in page-lyr.tex} \wait
755\fi
756
757\definelayer
758  [OTRTEXT]
759
760\setuplayer
761  [OTRTEXT]
762  [\c!width=\innermakeupwidth,
763   \c!height=\textheight]
764
765\aliased\let\normalsettextpagecontent\settextpagecontent % will be overloaded in page-spr
766
767\overloaded\aliased\let\normalsettextpagecontent\settextpagecontent % will be overloaded in page-spr
768
769\permanent\overloaded\protected\def\settextpagecontent#1#2#3% #2 and #3 will disappear
770  {\doifelselayerdata{OTRTEXT}
771     {\setbox#1\hpack to \makeupwidth
772        {\startoverlay
773           {\tightlayer[OTRTEXT]} % first, otherwise problems with toc
774           {\normalsettextpagecontent{#1}{#2}{#3}\box#1}
775         \stopoverlay}%
776      \dp#1\zeropoint}%
777     {\normalsettextpagecontent{#1}{#2}{#3}}}
778
779\protect \endinput
780