summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv/pack-lyr.mkxl
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/mkiv/pack-lyr.mkxl')
-rw-r--r--tex/context/base/mkiv/pack-lyr.mkxl794
1 files changed, 794 insertions, 0 deletions
diff --git a/tex/context/base/mkiv/pack-lyr.mkxl b/tex/context/base/mkiv/pack-lyr.mkxl
new file mode 100644
index 000000000..838e2fe19
--- /dev/null
+++ b/tex/context/base/mkiv/pack-lyr.mkxl
@@ -0,0 +1,794 @@
+%D \module
+%D [ file=pack-lyr,
+%D version=2000.10.20,
+%D title=\CONTEXT\ Packaging Macros,
+%D subtitle=Layers,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Packaging Macros / Layers}
+
+% todo : first / last / next / +... => page key
+% test on left/right box when no doublesided option given
+% use \ifcsname instead of doifvalue
+
+\unprotect
+
+% When being backgrounds layers get the background offset displacement. Should be
+% an option, on by default (compatibility).
+
+%D The layering mechanism implemented here is independent of the output routine, but
+%D future extensions may depend on a more close cooperation.
+%D
+%D First we overload a macro from \type {pack-rul}. From now on we accept a
+%D (optional) argument: the specific layer it will go in. This means that we can
+%D move an overlay from one background to the other using the dimensions of the
+%D parent.
+
+\ifdefined\defineoverlay \else \message{loaded to early} \wait \fi
+
+\unexpanded\def\defineoverlay
+ {\dotripleempty\pack_framed_define_overlay}
+
+\def\pack_framed_define_overlay[#1][#2][#3]% overlay [layer] content
+ {\ifthirdargument
+ %\writestatus{BEWARE}{This (overlay definition) has changed!}% temp
+ \def\pack_framed_define_overlay_indeed##1{\setvalue{\??overlay##1}{\setlayer[#2]{\executedefinedoverlay{##1}{#3}}}}%
+ \else
+ \def\pack_framed_define_overlay_indeed##1{\setvalue{\??overlay##1}{\executedefinedoverlay{##1}{#2}}}%
+ \fi
+ \processcommalist[#1]\pack_framed_define_overlay_indeed}
+
+%D We use the command handler code. The previous, more direct parameter handling was
+%D 25\% faster when no parameters were passed when adding content to a layer.
+%D However, when we pass for instance a preset, the new methos is some 10\% faster
+%D and it happens that in most cases we do pass some parameters. It would be
+%D interesting to see if we can push the preset in between the regular chain but it
+%D could also lead to unwanted side effects when nesting layer placement.
+
+\installcorenamespace{layer}
+\installcorenamespace{layerbox}
+\installcorenamespace{layerpreset}
+\installcorenamespace{layerposition} % brr, unreadable
+
+%D \macros
+%D {definelayer,setuplayer}
+%D
+%D Each layer gets its own (global) box. This also means that the data that goes
+%D into a layer, is typeset immediately. Each layer automatically gets an associated
+%D overlay, which can be used in any background assignment.
+%D
+%D After a layer is defined, you can change its characteristics.
+
+\installcommandhandler \??layer {layer} \??layer
+
+\setuplayer
+ [\c!state=\v!start,
+ %\c!doublesided=,
+ %\c!preset=,
+ %\c!option=,
+ %\c!corner=,
+ %\c!page=,
+ %\c!rotation=, % geen 0 !
+ \c!direction=\v!normal,
+ \c!position=\v!no,
+ \c!method=\v!overlay,
+ \c!x=\zeropoint,
+ \c!y=\zeropoint,
+ \c!line=0,
+ \c!column=0,
+ \c!width=\wd\nextbox, % don't change this globally
+ \c!height=\ht\nextbox, % don't change this globally
+ \c!offset=\zeropoint,
+ \c!hoffset=\zeropoint,
+ \c!voffset=\zeropoint,
+ \c!dx=\zeropoint,
+ \c!dy=\zeropoint,
+ \c!location=rb,
+ \c!sx=1,
+ \c!sy=1,
+ \c!region=\layeranchor]
+
+\def\layeranchor{\currentlayer:\the\realpageno}
+
+\let\p_pack_layers_doublesided\empty
+\let\p_pack_layers_state \empty
+\let\p_pack_layers_option \empty
+\let\p_pack_layers_method \empty
+\let\p_pack_layers_preset \empty
+\let\p_pack_layers_rotation \empty
+\let\p_pack_layers_position \empty
+\let\p_pack_layers_hoffset \empty
+\let\p_pack_layers_voffset \empty
+\let\p_pack_layers_offset \empty
+\let\p_pack_layers_dx \empty
+\let\p_pack_layers_dy \empty
+\let\p_pack_layers_sx \empty
+\let\p_pack_layers_sy \empty
+\let\p_pack_layers_x \empty
+\let\p_pack_layers_y \empty
+\let\p_pack_layers_corner \empty
+\let\p_pack_layers_location \empty
+\let\p_pack_layers_line \empty
+\let\p_pack_layers_column \empty
+\let\p_pack_layers_width \empty
+\let\p_pack_layers_height \empty
+\let\p_pack_layers_direction \empty
+\let\p_pack_layers_region \empty
+
+\let\m_pack_layers_page \empty
+\let\m_pack_layers_target \empty
+\let\m_pack_layers_region \empty
+\let\m_pack_layers_anchor \empty
+
+\newconditional\c_pack_layers_repeated
+\newconditional\c_pack_layers_trace
+\newcount \c_pack_layers_current_data
+
+\newbox\b_layers
+
+\newdimen\d_pack_layers_x_size
+\newdimen\d_pack_layers_y_size
+\newdimen\d_pack_layers_x_offset
+\newdimen\d_pack_layers_y_offset
+\newdimen\d_pack_layers_x_position
+\newdimen\d_pack_layers_y_position
+
+\newdimen\layerwidth
+\newdimen\layerheight
+
+\let\lastlayerxpos\!!zeropoint
+\let\lastlayerypos\!!zeropoint
+\let\lastlayerwd \!!zeropoint
+\let\lastlayerht \!!zeropoint
+\let\lastlayerdp \!!zeropoint
+
+\appendtoks
+ \edef\p_pack_layers_doublesided{\layerparameter\c!doublesided}%
+ \ifx\p_pack_layers_doublesided\v!yes
+ \relateparameterhandlers{layer}{\v!left \currentlayer}{layer}\currentlayer % permits left*
+ \relateparameterhandlers{layer}{\v!right\currentlayer}{layer}\currentlayer % permits right*
+ \pack_layers_preset_box{\v!left \currentlayer}%
+ \pack_layers_preset_box{\v!right\currentlayer}%
+ \fi
+ \pack_layers_preset_box\currentlayer
+ \normalexpanded{\defineoverlay[\currentlayer][\noexpand\composedlayer{\currentlayer}]}%
+\to \everydefinelayer
+
+\def\pack_layers_preset_box#1%
+ {\ifcsname\??layerbox#1\endcsname
+ \resetlayer[#1]%
+ \else
+ \expandafter\newbox\csname\??layerbox#1\endcsname
+ \fi}
+
+%D \macros
+%D {resetlayer}
+%D
+%D This macro hardly needs an explanation (but is seldom needed anyway).
+
+\def\pack_layers_reset_box#1%
+ {\ifcsname\??layerbox#1\endcsname
+ %\global\setbox\csname\??layerbox#1\endcsname\emptybox
+ \global\setbox\lastnamedcs\emptybox
+ \fi}
+
+\def\resetlayer[#1]%
+ {\pack_layers_reset_box{#1}%
+ \pack_layers_reset_box{\v!left #1}%
+ \pack_layers_reset_box{\v!right#1}%
+ \pack_layers_reset_box{#1:\the\realpageno}}
+
+%D \macros
+%D {setlayer}
+%D
+%D Data is moved into a layer with the following macro. When \type {position} is
+%D set, relative positioning is used, with the current point as reference point.
+%D Otherwise the topleft corner is used as reference point.
+%D
+%D \starttyping
+%D \setlayer [identifier] [optional parameters] {data}
+%D \stoptyping
+
+\def\setcurrentlayerdimensions
+ {\dodoubleempty\pack_layers_set_current_dimensions}
+
+\def\pack_layers_set_current_dimensions[#1][#2]% name left|right
+ {\edef\currentlayerwidth {\thelayerwidth {#2#1}}%
+ \edef\currentlayerheight{\thelayerheight{#2#1}}}
+
+\def\thelayerwidth #1{\the\ifcsname\??layerbox#1\endcsname\wd\lastnamedcs\else\zeropoint\fi}
+\def\thelayerheight#1{\the\ifcsname\??layerbox#1\endcsname\ht\lastnamedcs\else\zeropoint\fi}
+
+\unexpanded\def\setlayer
+ {\dotripleempty\pack_layers_set}
+
+\def\pack_layers_set[#1][#2][#3]% #4 == box do \fi is ok
+ {\bgroup
+ \checkpositionoverlays % otherwise funny regions
+ \edef\currentlayer{#1}%
+ \edef\p_pack_layers_state{\layerparameter\c!state}%
+ \ifx\p_pack_layers_state\v!stop
+ \dowithnextboxcs\egroup\hbox % no pack ?
+ \orelse\ifthirdargument
+ \pack_layers_set_indeed[#1][#2][#3]%
+ \else
+ \ifcondition\validassignment{#2}%
+ \pack_layers_set_indeed[#1][][#2]%
+ \else
+ \pack_layers_set_indeed[#1][#2][]%
+ \fi
+ \fi}
+
+\def\pack_layers_set_indeed[#1][#2][#3]% #2 = links/rechts
+ {\page_backgrounds_recalculate % brrr
+ \global\advance\c_pack_layers_current_data\plusone
+ \forgetall
+ \dontcomplain
+ \edef\p_pack_layers_option{\layerparameter\c!option}%
+ \ifx\p_pack_layers_option\v!test
+ \settrue\c_pack_layers_trace
+ \traceboxplacementtrue
+ \fi
+ \edef\m_pack_layers_target{#2}%
+ \dowithnextbox{\pack_layers_set_finish{#3}}\hbox}
+
+\def\pack_layers_set_finish#1%
+ {\ifcsname\??layerbox\currentlayer\endcsname % can move up
+ \ifx\m_pack_layers_target\v!even
+ \ifodd\realpageno
+ % discard nextbox
+ \else
+ \let\m_pack_layers_target\v!left
+ \pack_layers_set_content{#1}%
+ \fi
+ \orelse\ifx\m_pack_layers_target\v!odd
+ \ifodd\realpageno
+ \let\m_pack_layers_target\v!right
+ \pack_layers_set_content{#1}%
+ \else
+ % discard nextbox
+ \fi
+ \else
+ \pack_layers_set_content{#1}%
+ \fi
+ \else
+ \writestatus{layer}{unknown layer \currentlayer}%
+ \fi
+ \egroup}
+
+% todo: left/right
+% todo: get position data in one go
+
+\def\pack_layers_set_last_position_yes % target: left|right
+ {% this will become one call
+ \edef\m_pack_layers_anchor{\??layerposition\the\c_pack_layers_current_data}%
+ \edef\m_pack_layers_page {\MPp\m_pack_layers_anchor}%
+ %edef\m_pack_layers_region{\MPr\m_pack_layers_anchor}% wrong one
+ \edef\m_pack_layers_region{\layerparameter\c!region}%
+ \d_pack_layers_x_position \dimexpr-\MPx\m_pack_layers_region+\MPx\m_pack_layers_anchor\relax
+ \d_pack_layers_y_position \dimexpr \MPy\m_pack_layers_region-\MPy\m_pack_layers_anchor+\MPh\m_pack_layers_region\relax
+ \xdef\lastlayerxpos{\the\d_pack_layers_x_position}%
+ \xdef\lastlayerypos{\the\d_pack_layers_y_position}%
+ % \writestatus{layering}{region: \m_pack_layers_region=>\MPxywhd\m_pack_layers_region}%
+ % \writestatus {}{anchor: \m_pack_layers_anchor=>\MPxywhd\m_pack_layers_anchor}%
+ % \writestatus {}{offset: \c!dx,\c!dy =>\lastlayerxpos,\lastlayerypos}%
+ \global\letlayerparameter\c!state\v!start % needed ?
+ \setbox\b_layers\vpack to \d_pack_layers_y_size
+ {\hpack to \d_pack_layers_x_size
+ {\xypos\m_pack_layers_anchor\hss}%
+ \vss}}
+
+\def\pack_layers_set_last_position_nop
+ {\setbox\b_layers\emptybox
+ \d_pack_layers_x_position\p_pack_layers_sx\dimexpr\p_pack_layers_x\relax
+ \d_pack_layers_y_position\p_pack_layers_sy\dimexpr\p_pack_layers_y\relax
+ \glet\lastlayerxpos\!!zeropoint
+ \glet\lastlayerypos\!!zeropoint
+ \doifinset\v!bottom\p_pack_layers_corner\pack_layers_set_bottom_positions
+ \doifinset\v!right \p_pack_layers_corner\pack_layers_set_right_positions
+ \doifinset\v!middle\p_pack_layers_corner\pack_layers_set_middle_positions
+ \edef\m_pack_layers_page{\layerparameter\c!page}}
+
+\unexpanded\def\definelayerpreset
+ {\dodoubleargument\pack_layers_define_preset}
+
+\def\pack_layers_define_preset[#1][#2]%
+ {\doifelseassignment{#2}
+ {\setvalue{\??layerpreset#1}{\setupcurrentlayer[#2]}}
+ {\setvalue{\??layerpreset#1}{\csname\??layerpreset#2\endcsname}}}
+
+\def\pack_layers_set_content#1%
+ {\layerwidth \layerparameter\c!width % global (local later)
+ \layerheight\layerparameter\c!height % global (local later)
+ \d_pack_layers_x_size\layerwidth
+ \d_pack_layers_y_size\layerheight
+ %
+ \setupcurrentlayer[#1]% preroll
+ %
+ \edef\p_pack_layers_preset {\layerparameter\c!preset }%
+ %
+ \ifcsname\??layerpreset\p_pack_layers_preset\endcsname
+ \lastnamedcs
+ \setupcurrentlayer[#1]% postroll
+ \fi
+ %
+ \edef\p_pack_layers_rotation {\layerparameter\c!rotation }%
+ \edef\p_pack_layers_position {\layerparameter\c!position }%
+ \edef\p_pack_layers_hoffset {\layerparameter\c!hoffset }%
+ \edef\p_pack_layers_voffset {\layerparameter\c!voffset }%
+ \edef\p_pack_layers_offset {\layerparameter\c!offset }%
+ \edef\p_pack_layers_dx {\layerparameter\c!dx }%
+ \edef\p_pack_layers_dy {\layerparameter\c!dy }%
+ \edef\p_pack_layers_sx {\layerparameter\c!sx }%
+ \edef\p_pack_layers_sy {\layerparameter\c!sy }%
+ \edef\p_pack_layers_x {\layerparameter\c!x }%
+ \edef\p_pack_layers_y {\layerparameter\c!y }%
+ \edef\p_pack_layers_corner {\layerparameter\c!corner }%
+ \edef\p_pack_layers_location {\layerparameter\c!location }%
+ \edef\p_pack_layers_line {\layerparameter\c!line }%
+ \edef\p_pack_layers_column {\layerparameter\c!column }%
+ \edef\p_pack_layers_width {\layerparameter\c!width }% local ones
+ \edef\p_pack_layers_height {\layerparameter\c!height }% local ones
+ \edef\p_pack_layers_direction{\layerparameter\c!direction}%
+ %
+ \ifx\p_pack_layers_position\v!overlay
+ \let\p_pack_layers_width \zeropoint
+ \let\p_pack_layers_height \zeropoint
+ \let\p_pack_layers_position\v!yes
+ \fi
+ \ifx\p_pack_layers_rotation\empty \else
+ % use direct call
+ \setbox\nextbox\hpack
+ {\rotate[\c!location=\v!high,\c!rotation=\layerparameter\c!rotation]{\box\nextbox}}%
+ \fi
+ \d_pack_layers_x_offset\p_pack_layers_sx\dimexpr
+ \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
+ \relax
+ \d_pack_layers_y_offset\p_pack_layers_sy\dimexpr
+ \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
+ \relax
+ \ifx\p_pack_layers_position\v!yes
+ \pack_layers_set_last_position_yes
+ \else
+ \pack_layers_set_last_position_nop
+ \fi
+ %
+ \ifx\m_pack_layers_page\empty \else % is expanded
+ \edef\m_pack_layers_page{:\m_pack_layers_page}%
+ \ifcsname\??layerbox\m_pack_layers_target\currentlayer\m_pack_layers_page\endcsname \else
+ \expandafter\newbox\csname\??layerbox\m_pack_layers_target\currentlayer\m_pack_layers_page\endcsname
+ \fi
+ \fi
+ \chardef\layerpagebox\csname\??layerbox\m_pack_layers_target\currentlayer\m_pack_layers_page\endcsname
+ \ifvoid\layerpagebox
+ \gsetboxllx\layerpagebox\zeropoint
+ \gsetboxlly\layerpagebox\zeropoint
+ \fi
+ \global\setbox\layerpagebox\vpack %to \layerparameter\c!height % new, otherwise no negative y possible
+ {\offinterlineskip
+ \ifvoid\layerpagebox
+ \let\lastlayerwidth \zeropoint
+ \let\lastlayerheight\zeropoint
+ \else
+ \edef\lastlayerwidth {\the\wd\layerpagebox}%
+ \edef\lastlayerheight{\the\ht\layerpagebox}%
+ \ht\layerpagebox\zeropoint
+ \dp\layerpagebox\zeropoint
+ \wd\layerpagebox\zeropoint
+ \ifx\p_pack_layers_direction\v!reverse\else
+ \box\layerpagebox
+ \fi
+ \fi
+ % don't move
+ \xdef\lastlayerwd{\the\wd\nextbox}%
+ \xdef\lastlayerht{\the\ht\nextbox}% % not entirely ok when grid !
+ \xdef\lastlayerdp{\the\dp\nextbox}% % not entirely ok when grid !
+ % this code
+ \ifx\p_pack_layers_location\v!grid
+ \ht\nextbox\strutheight
+ \dp\nextbox\strutdepth
+ \else
+ \setbox\nextbox\hpack
+ {\alignedbox[\p_pack_layers_location]\vpack{\box\nextbox}}%
+ \fi
+ \ifnum\p_pack_layers_line=\zerocount\else % no \ifcase, can be negative
+ \advance\d_pack_layers_y_position\dimexpr\p_pack_layers_line\lineheight+\topskip-\lineheight-\ht\nextbox\relax
+ \fi
+ \ifnum\p_pack_layers_column=\zerocount\else % no \ifcase, can be negative
+ \advance\d_pack_layers_x_position\layoutcolumnoffset\p_pack_layers_column\relax
+ \fi
+ \ifx\p_pack_layers_location\v!grid
+ \setbox\nextbox\hpack
+ {\alignedbox[rb]\vpack{\box\nextbox}}%
+ \fi
+ % ll registration
+ \scratchdimen\dimexpr\d_pack_layers_x_position+\d_pack_layers_x_offset\relax
+ \ifdim\scratchdimen<\getboxllx\layerpagebox
+ \gsetboxllx\layerpagebox\scratchdimen
+ \fi
+ \advance\scratchdimen\wd\nextbox
+ \wd\nextbox\ifdim\scratchdimen>\lastlayerwidth \scratchdimen \else \lastlayerwidth \fi
+ \scratchdimen\dimexpr\d_pack_layers_y_position+\d_pack_layers_y_offset\relax
+ \ifdim\scratchdimen<\getboxlly\layerpagebox
+ \gsetboxlly\layerpagebox\scratchdimen
+ \fi
+ % ll compensation
+ \advance\scratchdimen\dimexpr\ht\nextbox+\dp\nextbox\relax
+ \ht\nextbox\ifdim\scratchdimen>\lastlayerheight \scratchdimen \else \lastlayerheight \fi
+ \dp\nextbox\zeropoint
+ % placement
+ \hsize\p_pack_layers_width
+ \vpack to \p_pack_layers_height \bgroup
+ \smashbox\nextbox
+ \vskip\dimexpr\d_pack_layers_y_position+\d_pack_layers_y_offset\relax
+ \hskip\dimexpr\d_pack_layers_x_position+\d_pack_layers_x_offset\relax
+ % or maybe instead of the \vskip
+ % \raise-\dimexpr\d_pack_layers_y_position+\d_pack_layers_y_offset\relax
+ \box\nextbox
+ \ifvoid\layerpagebox
+ % already flushed
+ \else
+ % the reverse case % check !
+ \vskip-\dimexpr\d_pack_layers_y_position+\d_pack_layers_y_offset\relax
+ \box\layerpagebox
+ \fi
+ \egroup}%
+ % when position is true, the layerbox holds the compensation and needs
+ % to be placed; never change this !
+ \ifvoid\b_layers \else
+ \box\b_layers
+ \fi}
+
+\def\pack_layers_set_bottom_positions
+ {\ifnum\p_pack_layers_line=\zerocount\else % can be < 0
+ \edef\p_pack_layers_line{\the\numexpr-\p_pack_layers_line+\layoutlines+\plusone\relax}% use counter instead ?
+ \fi
+ \ifdim\d_pack_layers_y_size>\zeropoint
+ \advance\d_pack_layers_y_position-\d_pack_layers_y_size
+ \d_pack_layers_y_position-\d_pack_layers_y_position
+ \d_pack_layers_y_offset-\d_pack_layers_y_offset
+ \fi}
+
+\def\pack_layers_set_right_positions
+ {\ifnum\p_pack_layers_column=\zerocount\else % can be < 0
+ \edef\p_pack_layers_column{\the\numexpr-\layerparameter\c!column+\layoutcolumns+\plusone\relax}% use counter instead ?
+ \fi
+ \ifdim\d_pack_layers_x_size>\zeropoint
+ \advance\d_pack_layers_x_position-\d_pack_layers_x_size
+ \d_pack_layers_x_position-\d_pack_layers_x_position
+ \d_pack_layers_x_offset-\d_pack_layers_x_offset
+ \fi}
+
+\def\pack_layers_set_middle_positions
+ {\ifdim\d_pack_layers_x_size>\zeropoint \advance\d_pack_layers_x_position.5\d_pack_layers_x_size \fi
+ \ifdim\d_pack_layers_y_size>\zeropoint \advance\d_pack_layers_y_position.5\d_pack_layers_y_size \fi}
+
+%D Given the task to be accomplished, the previous macro is not even that
+%D complicated. It mainly comes down to skipping to the right place and placing a
+%D box on top of or below the existing content. In the case of position tracking,
+%D another reference point is chosen.
+
+%D \macros
+%D {doifelselayerdata}
+
+\def\doifelselayerdata#1%
+ {\ifcsname\??layerbox#1\endcsname
+ %\ifvoid\csname\??layerbox#1\endcsname
+ \ifvoid\lastnamedcs
+ \doubleexpandafter\secondoftwoarguments
+ \else
+ \doubleexpandafter\firstoftwoarguments
+ \fi
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\let\doiflayerdataelse\doifelselayerdata
+
+%D \macros
+%D {flushlayer}
+%D
+%D When we flush a layer, we flush both the main one and the page dependent one
+%D (when defined). This feature is more efficient in \ETEX\ since there testing for
+%D an undefined macro does not takes hash space.
+
+% todo: setups before flush, handy hook
+
+\unexpanded\def\flushlayer[#1]% quite core, so optimized (todo: check for void)
+ {\begingroup
+ \forgetall
+ \edef\currentlayer{#1}%
+ \edef\p_pack_layers_state{\layerparameter\c!state}%
+ \ifx\p_pack_layers_state\v!stop
+ % nothing
+ \orelse\ifx\p_pack_layers_state\v!next
+ \global\letlayerparameter\c!state\v!start % dangerous, stack-built-up
+ \orelse\ifx\p_pack_layers_state\v!continue
+ \global\letlayerparameter\c!state\v!repeat % dangerous, stack-built-up
+ \else
+ \edef\p_pack_layers_doublesided{\layerparameter\c!doublesided}%
+ \ifx\p_pack_layers_doublesided\v!yes
+ \ifcsname\??layerbox#1\endcsname
+ % we can make a dedicated one for this
+ \doifbothsidesoverruled
+ {\pack_layers_flush_double\v!left }%
+ {\pack_layers_flush_double\v!right}%
+ {\pack_layers_flush_double\v!left }%
+ \else
+ \pack_layers_flush_single
+ \fi
+ \else
+ \pack_layers_flush_single
+ \fi
+ \fi
+ \endgroup}
+
+% \def\pack_layers_flush_single
+% {\startoverlay
+% {\ifcsname\??layerbox \currentlayer \endcsname\pack_layers_flush_indeed\plusone \currentlayer \fi}%
+% {\ifcsname\??layerbox \currentlayer:\the\realpageno\endcsname\pack_layers_flush_indeed\zerocount{\currentlayer:\the\realpageno}\fi}%
+% \stopoverlay}
+%
+% \def\pack_layers_flush_double#1%
+% {\startoverlay
+% {\ifcsname\??layerbox \currentlayer \endcsname\pack_layers_flush_indeed\plusone \currentlayer \fi}%
+% {\ifcsname\??layerbox \currentlayer:\the\realpageno\endcsname\pack_layers_flush_indeed\zerocount {\currentlayer:\the\realpageno}\fi}%
+% {\ifcsname\??layerbox#1\currentlayer \endcsname\pack_layers_flush_indeed\plusone {#1\currentlayer }\fi}%
+% {\ifcsname\??layerbox#1\currentlayer:\the\realpageno\endcsname\pack_layers_flush_indeed\zerocount{#1\currentlayer:\the\realpageno}\fi}%
+% \stopoverlay}
+
+% optimized:
+
+\def\pack_layers_flush_single
+ {\ifcsname\??layerbox\currentlayer\endcsname
+ \ifvoid\lastnamedcs
+ \ifcsname\??layerbox\currentlayer:\the\realpageno\endcsname
+ \ifvoid\lastnamedcs\else
+ \chardef\b_layer_two\lastnamedcs
+ \pack_layers_flush_indeed\zerocount{\currentlayer:\the\realpageno}\b_layer_two
+ \fi
+ \fi
+ \else
+ \chardef\b_layer_one\lastnamedcs
+ \ifcsname\??layerbox\currentlayer:\the\realpageno\endcsname
+ \ifvoid\lastnamedcs\else
+ \chardef\b_layer_two\lastnamedcs
+ \startoverlay
+ {\pack_layers_flush_indeed\plusone \currentlayer \b_layer_one}%
+ {\pack_layers_flush_indeed\zerocount{\currentlayer:\the\realpageno}\b_layer_two}%
+ \stopoverlay
+ \fi
+ \else
+ \pack_layers_flush_indeed\plusone\currentlayer\b_layer_one
+ \fi
+ \fi
+ \orelse\ifcsname\??layerbox\currentlayer:\the\realpageno\endcsname
+ \ifvoid\lastnamedcs
+ % nothing
+ \else
+ \chardef\b_layer_two\lastnamedcs
+ \pack_layers_flush_indeed\zerocount{\currentlayer:\the\realpageno}\b_layer_two
+ \fi
+ \fi}
+
+% less optimized:
+
+\def\pack_layers_flush_double#1%
+ {\startoverlay
+ {\ifcsname\??layerbox\currentlayer\endcsname
+ \ifvoid\lastnamedcss\else \chardef\b_layer_two\lastnamedcs
+ \pack_layers_flush_indeed\plusone\currentlayer\b_layer_two
+ \fi
+ \fi}%
+ {\ifcsname\??layerbox\currentlayer:\the\realpageno\endcsname
+ \ifvoid\lastnamedcss\else \chardef\b_layer_two\lastnamedcs
+ \pack_layers_flush_indeed\zerocount{\currentlayer:\the\realpageno}\b_layer_two
+ \fi
+ \fi}%
+ {\ifcsname\??layerbox#1\currentlayer\endcsname
+ \ifvoid\lastnamedcss\else \chardef\b_layer_two\lastnamedcs
+ \pack_layers_flush_indeed\plusone{#1\currentlayer}\b_layer_two
+ \fi
+ \fi}%
+ {\ifcsname\??layerbox#1\currentlayer:\the\realpageno\endcsname
+ \ifvoid\lastnamedcss\else \chardef\b_layer_two\lastnamedcs
+ \pack_layers_flush_indeed\zerocount{#1\currentlayer:\the\realpageno}\b_layer_two
+ \fi
+ \fi}%
+ \stopoverlay}
+
+\let\pack_layers_top_fill \relax
+\let\pack_layers_bottom_fill\vss
+
+%def\pack_layers_flush_indeed#1#2%
+\def\pack_layers_flush_indeed#1#2#3%
+ {\begingroup % already grouped
+ \offinterlineskip
+ \edef\p_pack_layers_preset{\layerparameter\c!preset}%
+ \ifcsname\??layerpreset\p_pack_layers_preset\endcsname
+ \lastnamedcs
+ \fi
+ \edef\p_pack_layers_method{\layerparameter\c!method}%
+ \edef\p_pack_layers_option{\layerparameter\c!option}%
+ \ifx\p_pack_layers_option\v!test
+ \settrue\c_pack_layers_trace
+ \traceboxplacementtrue
+ \fi
+ \ifcase#1\relax
+ \setfalse\c_pack_layers_repeated
+ \else
+ \edef\p_pack_layers_position{\layerparameter\c!position}%
+ \ifx\p_pack_layers_position\v!yes
+ \setfalse\c_pack_layers_repeated
+ \else
+ \edef\p_pack_layers_repeat{\layerparameter\c!repeat}%
+ \ifx\p_pack_layers_repeat\v!yes
+ \settrue\c_pack_layers_repeated
+ \orelse\ifx\p_pack_layers_state\v!repeat
+ \settrue\c_pack_layers_repeated
+ \else
+ \setfalse\c_pack_layers_repeated
+ \fi
+ \fi
+ \fi
+ %chardef\b_layers\csname\??layerbox#2\endcsname % trick
+ \let\b_layers#3%
+ % we need to copy in order to retain the negative offsets for a next
+ % stage of additions, i.e. llx/lly accumulate in repeat mode and the
+ % compensation may differ each flush depending on added content
+ \setbox\nextbox
+ \ifx\p_pack_layers_method\v!fit
+ \pack_layers_positioned_box_yes
+ \else
+ \pack_layers_positioned_box_nop
+ \fi
+ % todo: method=offset => overlayoffset right/down (handy for backgrounds with offset)
+ \doifelseoverlay{#2}%
+ {\setlayoutcomponentattribute{\v!layer:#2}}%
+ \resetlayoutcomponentattribute
+ % we have conflicting demands: some mechanisms want ll anchoring .. I need to figure this out
+ % and maybe we will have 'origin=bottom' or so
+ \setbox\nextbox
+ \ifx\p_pack_layers_option\v!test \ruledvbox \else \vpack \fi \ifx\p_pack_layers_method\v!overlay to \d_overlay_height \fi \layoutcomponentboxattribute
+ {\pack_layers_top_fill
+%
+% \hpack \ifx\p_pack_layers_method\v!overlay to \d_overlay_width \fi
+% {\box\nextbox
+% \hss}%
+%
+ \ifx\p_pack_layers_method\v!overlay \wd\nextbox\d_overlay_width\fi
+ \box\nextbox
+%
+ \pack_layers_bottom_fill}%
+ % \edef\currentlayer{#2}% :\the\realpageno}% local .. check \anchor
+ % \edef\p_pack_layers_position{\layerparameter\c!position}% local
+ \ifx\p_pack_layers_position\v!yes
+ \edef\p_pack_layers_region{\layerparameter\c!region}%
+ \ifx\p_pack_layers_region\empty
+ \else
+ \anch_mark_tagged_box\nextbox\p_pack_layers_region % was \layeranchor
+ \fi
+ \fi
+ \box\nextbox
+ %
+ \ifconditional\c_pack_layers_repeated\else
+ \gsetboxllx\b_layers\zeropoint
+ \gsetboxlly\b_layers\zeropoint
+ \fi
+ \endgroup}
+
+\def\pack_layers_positioned_box_yes
+ {\vpack
+ {\vskip-\getboxlly\b_layers
+ \hskip-\getboxllx\b_layers
+ \hsize-\dimexpr\getboxllx\b_layers-\wd\b_layers\relax
+ \ifconditional\c_pack_layers_repeated\copy\else\box\fi\b_layers}}
+
+\def\pack_layers_positioned_box_nop
+ {\ifconditional\c_pack_layers_repeated\copy\else\box\fi\b_layers}
+
+% \definelayer[test][method=fit] \setupcolors[state=start,option=test]
+%
+% \framed[framecolor=red,offset=overlay]{\setlayer[test]{aa}\setlayer[test][x=10pt]{g}\flushlayer[test]}
+% \framed[framecolor=red,offset=overlay]{\setlayer[test]{aa}\setlayer[test][x=-10pt]{bb}\flushlayer[test]}
+% \framed[framecolor=red,offset=overlay]{\setlayer[test][x=-20pt]{cccccc}\flushlayer[test]}
+% \framed[framecolor=red,offset=overlay]{\setlayer[test]{dd}\setlayer[test][x=-20pt,y=-3pt]{eeeeee}\flushlayer[test]}
+
+%D \macros
+%D {composedlayer,placelayer,tightlayer}
+%D
+%D This is a handy shortcut, which saves a couple of braces when we use it as
+%D parameter. This name also suits better to other layering commands.
+
+\unexpanded\def\composedlayer#1{\flushlayer[#1]}
+
+\unexpanded\def\tightlayer[#1]%
+ {\hpack
+ {\def\currentlayer{#1}% todo: left/right
+ \setbox\nextbox\emptybox
+ \d_overlay_width \layerparameter\c!width
+ \d_overlay_height\layerparameter\c!height
+ \composedlayer{#1}}}
+
+\let\placelayer\flushlayer
+
+%D \macros
+%D {setMPlayer}
+%D
+%D The following layer macro uses the positions that are registered by \METAPOST.
+%D
+%D \starttyping
+%D \definelayer[test]
+%D
+%D \setMPlayer [test] [somepos-1] {Whatever we want here!}
+%D \setMPlayer [test] [somepos-2] {Whatever we need there!}
+%D \setMPlayer [test] [somepos-3] {\externalfigure[cow.mps][width=2cm]}
+%D
+%D \startuseMPgraphic{oeps}
+%D draw fullcircle scaled 10cm withcolor red ;
+%D register ("somepos-1",2cm,3cm,center currentpicture) ;
+%D register ("somepos-2",8cm,5cm,(-1cm,-2cm)) ;
+%D register ("somepos-3",0cm,0cm,(-2cm,2cm)) ;
+%D \stopuseMPgraphic
+%D
+%D \getMPlayer[test]{\useMPgraphic{oeps}}
+%D \stoptyping
+%D
+%D The last line is equivalent to
+%D
+%D \starttyping
+%D \framed
+%D [background={foreground,test},offset=overlay]
+%D {\useMPgraphic{oeps}}
+%D \stoptyping
+
+\unexpanded\def\setMPlayer
+ {\dotripleempty\pack_layers_set_MP}
+
+\def\MPlayerwidth {\hsize}
+\def\MPlayerheight{\vsize}
+
+\def\pack_layers_set_MP[#1][#2][#3]%
+ {\edef\MPlayerwidth {\MPw{#2}}%
+ \edef\MPlayerheight{\MPh{#2}}%
+ \setlayer[#1][\c!x=\MPx{#2},\c!y=\MPy{#2},\c!position=\v!no,#3]}
+
+\unexpanded\def\getMPlayer
+ {\dodoubleempty\pack_layers_get_MP}
+
+\def\pack_layers_get_MP[#1][#2]%
+ {\framed[\c!background={\v!foreground,#1},\c!frame=\v!off,\c!offset=\v!overlay,#2]} % takes argument
+
+%D Watch out, a redefinition:
+
+\ifdefined\settextpagecontent \else
+ \writestatus\m!system{error in page-lyr.tex} \wait
+\fi
+
+\definelayer
+ [OTRTEXT]
+
+\setuplayer
+ [OTRTEXT]
+ [\c!width=\innermakeupwidth,
+ \c!height=\textheight]
+
+\let\normalsettextpagecontent\settextpagecontent % will be overloaded in page-spr
+
+\unexpanded\def\settextpagecontent#1#2#3% #2 and #3 will disappear
+ {\doifelselayerdata{OTRTEXT}
+ {\setbox#1\hpack to \makeupwidth
+ {\startoverlay
+ {\tightlayer[OTRTEXT]} % first, otherwise problems with toc
+ {\normalsettextpagecontent{#1}{#2}{#3}\box#1}
+ \stopoverlay}%
+ \dp#1\zeropoint}%
+ {\normalsettextpagecontent{#1}{#2}{#3}}}
+
+\protect \endinput