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