%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 \pushoverloadmode \permanent\overloaded\tolerant\protected\def\defineoverlay[#1]#*[#S#2]#*[#S#3]% overlay [layer] content {\ifnum\lastarguments=\plusthree %\writestatus{BEWARE}{This (overlay definition) has changed!}% temp \def\pack_framed_define_overlay_indeed##1{\defcsname\??overlay##1\endcsname{\setlayer[#2]{\executedefinedoverlay{##1}{#3}}}}% \else \def\pack_framed_define_overlay_indeed##1{\defcsname\??overlay##1\endcsname{\executedefinedoverlay{##1}{#2}}}% \fi \processcommalist[#1]\pack_framed_define_overlay_indeed} \popoverloadmode %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] \permanent\def\layeranchor{\currentlayer:\the\realpageno} \lettonothing\m_pack_layers_anchor \lettonothing\m_pack_layers_page \lettonothing\m_pack_layers_region \lettonothing\m_pack_layers_target \lettonothing\p_pack_layers_column \lettonothing\p_pack_layers_corner \lettonothing\p_pack_layers_dx \lettonothing\p_pack_layers_dy \lettonothing\p_pack_layers_height \lettonothing\p_pack_layers_hoffset \lettonothing\p_pack_layers_line \lettonothing\p_pack_layers_location \lettonothing\p_pack_layers_method \lettonothing\p_pack_layers_offset \lettonothing\p_pack_layers_option \lettonothing\p_pack_layers_position \lettonothing\p_pack_layers_preset \lettonothing\p_pack_layers_region \lettonothing\p_pack_layers_repeat \lettonothing\p_pack_layers_rotation \lettonothing\p_pack_layers_state \lettonothing\p_pack_layers_sx \lettonothing\p_pack_layers_sy \lettonothing\p_pack_layers_voffset \lettonothing\p_pack_layers_width \lettonothing\p_pack_layers_x \lettonothing\p_pack_layers_y \newconditional\c_pack_layers_repeated \newconditional\c_pack_layers_trace \newinteger \c_pack_layers_current_data \newbox\b_layers \pushoverloadmode \mutable\let\b_layers\b_layers \popoverloadmode \newdimension\d_pack_layers_x_size \newdimension\d_pack_layers_y_size \newdimension\d_pack_layers_x_offset \newdimension\d_pack_layers_y_offset \newdimension\d_pack_layers_x_position \newdimension\d_pack_layers_y_position \newdimension\layerwidth \newdimension\layerheight \mutable\let\lastlayerxpos\!!zeropoint \mutable\let\lastlayerypos\!!zeropoint \mutable\let\lastlayerwd \!!zeropoint \mutable\let\lastlayerht \!!zeropoint \mutable\let\lastlayerdp \!!zeropoint \appendtoks \ifcstok{\layerparameter\c!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} \permanent\protected\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 \mutable\lettonothing\currentlayerwidth \mutable\lettonothing\currentlayerheight \permanent\tolerant\protected\def\setcurrentlayerdimensions[#1]#*[#2]% name left|right {\edef\currentlayerwidth {\thelayerwidth {#2#1}}% \edef\currentlayerheight{\thelayerheight{#2#1}}} \permanent\def\thelayerwidth #1{\the\ifcsname\??layerbox#1\endcsname\wd\lastnamedcs\else\zeropoint\fi} \permanent\def\thelayerheight#1{\the\ifcsname\??layerbox#1\endcsname\ht\lastnamedcs\else\zeropoint\fi} \permanent\tolerant\protected\def\setlayer[#1]#*[#S#2]#*[#S#3]% #4 == box do \fi is ok {\bgroup \nofarguments\lastarguments \checkpositionoverlays % otherwise funny regions \cdef\currentlayer{#1}% \edef\p_pack_layers_state{\layerparameter\c!state}% \ifx\p_pack_layers_state\v!stop \dowithnextboxcs\egroup\hbox % no pack ? \orelse\ifnum\nofarguments=\plusthree \edef\m_pack_layers_target{#2}% \pack_layers_set_indeed{#3}% \orelse\ifhastok={#2}% \lettonothing\m_pack_layers_target \pack_layers_set_indeed{#2}% \else \edef\m_pack_layers_target{#2}% \pack_layers_set_indeed\empty \fi} \def\pack_layers_set_indeed#1% {\page_backgrounds_recalculate % brrr \global\advanceby\c_pack_layers_current_data\plusone \forgetall \dontcomplain \edef\p_pack_layers_option{\layerparameter\c!option}% \ifx\p_pack_layers_option\v!test \c_pack_layers_trace\conditionaltrue \traceboxplacementtrue \fi \dowithnextbox{\pack_layers_set_finish{#1}}\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 \ifinset\v!bottom\p_pack_layers_corner\pack_layers_set_bottom_positions\fi \ifinset\v!right \p_pack_layers_corner\pack_layers_set_right_positions \fi \ifinset\v!middle\p_pack_layers_corner\pack_layers_set_middle_positions\fi \edef\m_pack_layers_page{\layerparameter\c!page}} \permanent\tolerant\protected\def\definelayerpreset[#1]#*[#S#2]% {\ifarguments\or \letcsname\??layerpreset#1\endcsname\empty \orelse\ifhastok={#2}% \defcsname\??layerpreset#1\endcsname{\setupcurrentlayer[#2]}% \else \defcsname\??layerpreset#1\endcsname{\csname\??layerpreset#2\endcsname}% \fi} \mutable\integerdef\b_layers_page\zerocount \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 % \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 \ifempty\p_pack_layers_rotation \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 % \ifempty\m_pack_layers_page \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 \integerdef\b_layers_page\csname\??layerbox\m_pack_layers_target\currentlayer\m_pack_layers_page\endcsname \ifvoid\b_layers_page \gsetboxllx\b_layers_page\zeropoint \gsetboxlly\b_layers_page\zeropoint \fi \global\setbox\b_layers_page\vpack %to \layerparameter\c!height % new, otherwise no negative y possible {\offinterlineskip \ifvoid\b_layers_page \scratchwidth \zeropoint \scratchheight\zeropoint \else \scratchwidth \wd\b_layers_page \scratchheight\ht\b_layers_page \ht\b_layers_page\zeropoint \dp\b_layers_page\zeropoint \wd\b_layers_page\zeropoint \ifcstok{\layerparameter\c!direction}\v!reverse\else \box\b_layers_page \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 % \ifzero\p_pack_layers_line\else % todo: test this \advanceby\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 % \ifzero\p_pack_layers_column\else % todo: test this \advanceby\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\b_layers_page \gsetboxllx\b_layers_page\scratchdimen \fi \advanceby\scratchdimen\wd\nextbox \wd\nextbox\ifdim\scratchdimen>\scratchwidth \scratchdimen \else \scratchwidth \fi \scratchdimen\dimexpr\d_pack_layers_y_position+\d_pack_layers_y_offset\relax \ifdim\scratchdimen<\getboxlly\b_layers_page \gsetboxlly\b_layers_page\scratchdimen \fi % ll compensation \advanceby\scratchdimen\dimexpr\ht\nextbox+\dp\nextbox\relax \ht\nextbox\ifdim\scratchdimen>\scratchheight \scratchdimen \else \scratchheight \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\b_layers_page % already flushed \else % the reverse case % check ! \vskip-\dimexpr\d_pack_layers_y_position+\d_pack_layers_y_offset\relax \box\b_layers_page \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 % {\ifzero\p_pack_layers_line\else % todo: test this \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 \advanceby\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 % {\ifzero\p_pack_layers_column\else % todo: test this \edef\p_pack_layers_column{\the\numexpr-\layerparameter\c!column+\layoutcolumns+\plusone\relax}% use counter instead ? \fi \ifdim\d_pack_layers_x_size>\zeropoint \advanceby\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 \advanceby\d_pack_layers_x_position.5\d_pack_layers_x_size \fi \ifdim\d_pack_layers_y_size>\zeropoint \advanceby\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} \permanent\def\doifelselayerdata#1% {\ifcsname\??layerbox#1\endcsname %\ifvoid\csname\??layerbox#1\endcsname \ifvoid\lastnamedcs \doubleexpandafter\secondoftwoarguments \else \doubleexpandafter\firstoftwoarguments \fi \else \expandafter\secondoftwoarguments \fi} \aliased\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 \permanent\protected\def\flushlayer[#1]% quite core, so optimized (todo: check for void) {\begingroup \forgetall \cdef\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 \orelse\ifcstok{\layerparameter\c!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 \endgroup} % optimized \mutable\integerdef\b_layer_one\zerocount \mutable\integerdef\b_layer_two\zerocount \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 % will be \integerdef \ifcsname\??layerbox\currentlayer:\the\realpageno\endcsname \ifvoid\lastnamedcs\else \chardef\b_layer_two\lastnamedcs % will be \integerdef \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\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#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 \c_pack_layers_trace\conditionaltrue \traceboxplacementtrue \fi \ifcase#1\relax \c_pack_layers_repeated\conditionalfalse \else \edef\p_pack_layers_position{\layerparameter\c!position}% \ifx\p_pack_layers_position\v!yes \c_pack_layers_repeated\conditionalfalse \else \edef\p_pack_layers_repeat{\layerparameter\c!repeat}% \ifx\p_pack_layers_repeat\v!yes \c_pack_layers_repeated\conditionaltrue \orelse\ifx\p_pack_layers_state\v!repeat \c_pack_layers_repeated\conditionaltrue \else \c_pack_layers_repeated\conditionalfalse \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}% % \cdef\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}% \ifempty\p_pack_layers_region\else \anch_mark_tagged_box\nextbox\p_pack_layers_region\zerocount % 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. \permanent\protected\def\composedlayer#1{\flushlayer[#1]} \permanent\protected\def\tightlayer[#1]% {\hpack {\cdef\currentlayer{#1}% todo: left/right \setbox\nextbox\emptybox \d_overlay_width \layerparameter\c!width \d_overlay_height\layerparameter\c!height \composedlayer{#1}}} \aliased\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 \mutable\def\MPlayerwidth {\hsize} \mutable\def\MPlayerheight{\vsize} \permanent\tolerant\protected\def\setMPlayer[#1]#*[#2]#*[S#3]% {\edef\MPlayerwidth {\MPw{#2}}% \edef\MPlayerheight{\MPh{#2}}% \setlayer[#1][\c!x=\MPx{#2},\c!y=\MPy{#2},\c!position=\v!no,#3]} \permanent\tolerant\protected\def\getMPlayer[#1]#*[#S#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] \aliased\let\normalsettextpagecontent\settextpagecontent % will be overloaded in page-spr \overloaded\aliased\let\normalsettextpagecontent\settextpagecontent % will be overloaded in page-spr \permanent\overloaded\protected\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