%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 ? \else\ifthirdargument \pack_layers_set_indeed[#1][#2][#3]% \else \doifelseassignment{#2} {\pack_layers_set_indeed[#1][][#2]}% {\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 \else\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\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 \else\ifx\p_pack_layers_state\v!next \global\letlayerparameter\c!state\v!start % dangerous, stack-built-up \else\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\fi\fi \endgroup} % \ifcase#1\else\writestatus{layer}{unknown layer #3}\fi % todo: pass the layer with \lastnamedcs % \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 \else\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\fi} % less optimized: \def\pack_layers_flush_double#1% {\startoverlay {\ifcsname\??layerbox\currentlayer\endcsname \ifvoid\lastnamedcs\else \chardef\b_layer_two\lastnamedcs \pack_layers_flush_indeed\plusone\currentlayer\b_layer_two \fi \fi}% {\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}% {\ifcsname\??layerbox#1\currentlayer\endcsname \ifvoid\lastnamedcs\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\lastnamedcs\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 \else\ifx\p_pack_layers_state\v!repeat \settrue\c_pack_layers_repeated \else \setfalse\c_pack_layers_repeated \fi\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}% \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]% % {\hbox % {\def\currentlayer{#1}% todo: left/right % \setbox\nextbox\emptybox % \hsize\layerparameter\c!width % \vsize\layerparameter\c!height % \composedlayer{#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