%D \module %D [ file=page-bck, % copied from main-001 %D version=1997.03.31, %D title=\CONTEXT\ Page Macros, %D subtitle=Backgrounds, %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 Page Macros / Backgrounds} % \chardef\kindofpagetextareas=1 will isolate graphics from backgrounds \unprotect % messages moved % messages moved % messages moved % messages moved % messages moved % messages moved % messages moved % messages moved %D \macros %D {recalculatebackgrounds} %D %D We use a couple of switches so that we can minimize the %D amount of background calculations. The main switch is set %D by the recalculate directive. %D %D \starttyping %D \recalculatebackgrounds %D \stoptyping %D %D Other modules may not directly set the switches %D themselves. \newif\ifnewbackground \newif\ifsomebackground %D For special purposes, users can question the \type %D {*background} mode. This mode is only available when %D typesetting the pagebody. %D %D \starttyping %D \startmode[*background] ... %D \stoptyping \appendtoks \ifsomebackground \ifnewbackground \setsystemmode\v!background \fi \fi \to \everybeforepagebody %D \macros %D {addmainbackground, addtextbackground, %D addpagebackground, addprintbackground} %D %D Apart from the previously mentioned directive, the %D interface between this module and the other modules %D is made up by four macros that add background to parts of %D the layout. %D %D \starttyping %D \addmainbackground %D \addtextbackground %D \addpagebackground %D \addprintbackground %D \stoptyping %D To minimize calculations, we keep track of the state of the %D background of each area. A previous implementation did %D check each call to the background calculation macro, but %D using an intermediate usage flag instead of testing each %D time saves about 3\% on a run with a couple of backgrounds. %D (On the 824 pages maps bibliography runtime went down from %D 309 to 299 seconds.) \def\checkbackground#1% {\edef\!!stringe{\??ma#1}% \doifelsevaluenothing{\!!stringe\c!background } {\doifelsevaluenothing{\!!stringe\c!foregroundcolor} {\doifelsevalue{\!!stringe\c!frame }\v!on\!!doneatrue {\doifelsevalue{\!!stringe\c!leftframe }\v!on\!!doneatrue {\doifelsevalue{\!!stringe\c!rightframe}\v!on\!!doneatrue {\doifelsevalue{\!!stringe\c!topframe }\v!on\!!doneatrue {\doifelsevalue{\!!stringe\c!bottomframe }\v!on\!!doneatrue \!!doneafalse}}}}} \!!doneatrue} \!!doneatrue \if!!donea \setusage \!!stringe \else \resetusage\!!stringe \fi} \def\ifsomebackgroundfound#1% {\ifusage{\??ma#1}} % \def\doifsomebackgroundelse#1#2#3% % {\ifusage{\??ma#1}#2\else#3\fi} \def\doifsomebackgroundelse#1% {\ifusage{\??ma#1}% \expandafter\firstoftwoarguments \else \expandafter\secondoftwoarguments \fi} %D The background mechanism falls back on the \type {\framed} %D macro. This means that all normal frame and overlay %D features can be used. \def\addsomebackground#1#2#3#4% area box width height / zero test added {\ifsomebackgroundfound#1\ifdim#3>\zeropoint\ifdim#4>\zeropoint \doifvaluesomething{\??ma#1\c!setups}{\setups[\getvalue{\??ma#1\c!setups}]}% should not produce funny spaces ! \setbox#2\vbox\fastlocalframed [\??ma#1] [\c!component=#1,\c!strut=\v!no,\c!offset=\v!overlay,\c!setups=,% \c!width=#3,\c!height=#4] {\dp#2\zeropoint\box#2}% \fi\fi\fi} %D There are quite some backgrounds. At the bottom layer, %D there is the {\em paper} background. This one is only %D used for special purposes, like annotations to documents. \def\addprintbackground#1% {\addsomebackground \v!paper#1\printpaperwidth\printpaperheight} %D The page backgrounds can be put behind the {\em left %D page}, the {\em right page} or {\em each page}. As with %D the paper background, these are calculated on each page. \def\addpagebackground#1% {\doifbothsidesoverruled {\addsomebackground\v!rightpage#1\paperwidth\paperheight} {\addsomebackground\v!rightpage#1\paperwidth\paperheight} {\addsomebackground\v!leftpage #1\paperwidth\paperheight}% \addsomebackground\v!page #1\paperwidth\paperheight} %D Then there are the 25 areas that make up the layout: {\em %D top, header, text, footer, bottom} times {\em left edge, %D left margin, text, right margin, right edge}. These are %D only recalculated when they change or when the \type %D {status} is set to \type {repeat}. \newbox\leftbackground \newbox\rightbackground \def\addmainbackground#1% todo: dimension spec {\ifsomebackground \ifnewbackground \setbackgroundboxes \fi \setbox#1\vbox {\offinterlineskip \doifmarginswapelse {\copy\leftbackground}{\copy\rightbackground}% \box#1}% \fi} %D Finaly there is an aditional {\em text} background, again %D useful for special purposes only. This one is calculated %D each time. The hidden backgrounds are not meant for users! \newconditional\hiddenbackgroundenabled \def\addtextbackground#1% {\ifconditional\hiddenbackgroundenabled \addsomebackground\v!hidden#1\makeupwidth\textheight % mine ! \fi \addsomebackground\v!text#1\makeupwidth\textheight} %D The next couple of macros implement the area backgrounds. %D As said, these are cached in dedicated boxes. The offsets %D and depth of the page are used for alignment purposes. \newdimen\pageoffset % bleed \newdimen\pagedepth \let\pagebackgroundhoffset\!!zeropoint \let\pagebackgroundvoffset\!!zeropoint \let\pagebackgrounddepth \!!zeropoint % \def\setbackgroundboxes % {\showmessage\m!layouts8\empty % \setbackgroundbox\leftbackground\relax % \ifdoublesided % \setbackgroundbox\rightbackground\doswapmargins % \fi % \doifnot\@@mastatus\v!herhaal{\global\newbackgroundfalse}} %D We need a bit more clever mechanism in order to handle %D layers well. This means that we cannot calculate both %D background at the same time since something may have %D changed halfway a page. \chardef\newrightbackground\zerocount \chardef\newleftbackground \zerocount \def\recalculatebackgrounds {\global\newbackgroundtrue} \def\setbackgroundboxes {\ifnewbackground \global\chardef\newrightbackground\plusone \global\chardef\newleftbackground\plusone \global\setbox\leftbackground\emptybox \global\setbox\rightbackground\emptybox \fi \doifbothsides {\ifcase\newleftbackground \else % \showmessage\m!layouts8\empty \setbackgroundbox\leftbackground\relax \global\chardef\newleftbackground\zerocount \global\chardef\newrightbackground\zerocount \fi} {\ifcase\newleftbackground \else % \showmessage\m!layouts8\empty \setbackgroundbox\leftbackground\relax \global\chardef\newleftbackground\zerocount \fi} {\ifcase\newrightbackground \else % \showmessage\m!layouts8\empty \setbackgroundbox\rightbackground\doswapmargins \global\chardef\newrightbackground\zerocount \fi}% \ifx\@@mastate\v!repeat\else\global\newbackgroundfalse\fi} \def\addmainbackground#1% todo: dimension spec {\ifsomebackground \setbackgroundboxes \setbox#1\vbox {\offinterlineskip \doifmarginswapelse {\copy\leftbackground} {\copy\rightbackground} \box#1}% \fi} \def\setbackgroundoffsets {\ifsomebackground \ifnewbackground \global\let\pagebackgroundhoffset\!!zeropoint \global\let\pagebackgroundvoffset\!!zeropoint \global\let\pagebackgrounddepth \!!zeropoint \doifsomebackgroundelse{\v!text\v!text}\donetrue\donefalse \ifdone\else\doifsomebackgroundelse\v!text\donetrue\donothing\fi \ifdone \bgroup \scratchdimen\getvalue{\??ma\v!page\c!offset}% \doifsomebackgroundelse{\v!top\v!text}\donothing {\doifsomebackgroundelse{\v!bottom\v!text}\donothing {\xdef\pagebackgroundhoffset{\the\scratchdimen}}}% \doifsomebackgroundelse{\v!text\v!rightedge}\donothing {\doifsomebackgroundelse{\v!text\v!leftedge}\donothing {\xdef\pagebackgroundvoffset{\the\scratchdimen}% \scratchdimen\getvalue{\??ma\v!page\c!depth}% \xdef\pagebackgrounddepth{\the\scratchdimen}}}% \egroup \fi \fi \fi} \appendtoks \setbackgroundoffsets \to \everybeforepagebody \newconditional\swapbackgroundmargins \settrue\swapbackgroundmargins \def\setbackgroundbox#1#2% {\global\setbox#1\vbox {\dontcomplain \swapmargins \ifconditional\swapbackgroundmargins \doifmarginswapelse \donothing {\swapmacros\v!rightmargin\v!leftmargin \swapmacros\v!rightedge \v!leftedge}% \fi \calculatereducedvsizes \offinterlineskip #2\relax \vskip\dimexpr-\topheight-\topdistance\relax \dodopagebodybackground\v!top\topheight \vskip\topdistance \dodopagebodybackground\v!header\headerheight \vskip\headerdistance \dodopagebodybackground\v!text\textheight \vskip\footerdistance \dodopagebodybackground\v!footer\footerheight \vskip\bottomdistance \dodopagebodybackground\v!bottom\bottomheight \vfilll}% \smashbox#1} \def\dodopagebodybackground#1#2% {\ifdim#2>\zeropoint % added, faster \setbox\scratchbox\vbox to #2 \bgroup\hbox\bgroup % \swapmargins \goleftonpage \dododopagebodybackground\leftedgewidth #2#1\v!leftedge \hskip\leftedgedistance \dododopagebodybackground\leftmarginwidth #2#1\v!leftmargin \hskip\leftmargindistance \dododopagebodybackground\makeupwidth #2#1\v!text \hskip\rightmargindistance \dododopagebodybackground\rightmarginwidth#2#1\v!rightmargin \hskip\rightedgedistance \dododopagebodybackground\rightedgewidth #2#1\v!rightedge \egroup\egroup \wd\scratchbox\zeropoint \box\scratchbox\relax \fi} \def\dododopagebodybackground#1#2#3#4% width height pos pos {\ifsomebackgroundfound{#3#4}% \ifdim#2>\zeropoint\relax \ifdim#1>\zeropoint\relax \doifvaluesomething{\??ma#3#4\c!setups}{\setups[\getvalue{\??ma#3#4\c!setups}]}% should not produce funny spaces ! \fastlocalframed [\??ma#3#4] [\c!component=#3-#4,\c!offset=\v!overlay,\c!setups=] {\vbox to #2{\vss\hbox to#1{\hss\getvalue{\??ma#3#4\c!command}\hss}\vss}}% \else \hskip#1% \fi \else \hskip#1% \fi \else \hskip#1% \fi} %D The background mechanism is quite demanding in terms or %D resources. We used to delay these definitions till runtime %D usage, but since today's \TEX's are large, we now do the %D work on forehand. %D %D \starttyping %D \setupbackgrounds [settings] %D \setupbackgrounds [paper,page,text,..] [settings] %D \setupbackgrounds [top,...] [leftedge,...] [settings] %D \stoptyping %D %D \showsetup{setupbackgrounds} %D %D Because the number of arguments runs from one to three, %D we need to check for it. \def\setupbackgrounds {\dotripleempty\dosetupbackgrounds} \def\dosetupbackgrounds[#1][#2][#3]% {\ifthirdargument \global\somebackgroundtrue \def\docommand##1% {\doifinsetelse{##1}{\v!paper,\v!page,\v!leftpage,\v!rightpage} {\getparameters[\??ma##1][#3]\checkbackground{##1}} {\def\dodocommand####1{\getparameters[\??ma##1####1][#3]\checkbackground{##1####1}}% \processcommalist[#2]\dodocommand}}% \processcommalist[#1]\docommand \else\ifsecondargument \global\somebackgroundtrue \doifcommonelse{#1}{\v!text,\v!hidden,\v!paper,\v!page,\v!leftpage,\v!rightpage} {\def\docommand##1{\getparameters[\??ma##1][#2]\checkbackground{##1}}% \processcommalist[#1]\docommand}% {\setupbackgrounds [#1]% [\v!leftedge,\v!leftmargin,\v!text,\v!rightmargin,\v!rightedge]% [#2]}% \else\iffirstargument \getparameters[\??ma][#1]% \fi\fi\fi \doifelsevalue{\??ma\v!page\c!offset}\v!overlay {\global\pageoffset\zeropoint} {\global\pageoffset\getvalue{\??ma\v!page\c!offset}}% \global\pagedepth\getvalue{\??ma\v!page\c!depth}% \xdef\pagebackgroundoffset{\the\pageoffset}% \xdef\pagebackgrounddepth {\the\pagedepth }% \doifelse\@@mastate\v!stop {\global\newbackgroundfalse} {\global\newbackgroundtrue }} \let\pagebackgroundoffset\!!zeropoint \let\pagebackgrounddepth \!!zeropoint %D Each areas (currently there are $1+3+25+1=30$ of them) %D has its own low level framed object associated. \presetlocalframed [\??ma\v!paper] \presetlocalframed [\??ma\v!page] \presetlocalframed [\??ma\v!leftpage] \presetlocalframed [\??ma\v!rightpage] \copyparameters [\??ma\v!paper\c!frame][\??ma\v!page] [\c!offset,\c!depth,\c!radius,\c!corner,\c!color,\c!screen] \copyparameters [\??ma\v!paper\c!background][\??ma\v!page] [\c!offset,\c!depth,\c!radius,\c!corner,\c!color,\c!screen] \copyparameters [\??ma\v!page\c!frame][\??ma\v!page] [\c!offset,\c!depth,\c!radius,\c!corner,\c!color,\c!screen] \copyparameters [\??ma\v!page\c!background][\??ma\v!page] [\c!offset,\c!depth,\c!radius,\c!corner,\c!color,\c!screen] \copyparameters [\??ma\v!leftpage\c!frame][\??ma\v!leftpage] [\c!offset,\c!depth,\c!radius,\c!corner,\c!color,\c!screen] \copyparameters [\??ma\v!leftpage\c!background][\??ma\v!leftpage] [\c!offset,\c!depth,\c!radius,\c!corner,\c!color,\c!screen] \copyparameters [\??ma\v!rightpage\c!frame][\??ma\v!rightpage] [\c!offset,\c!depth,\c!radius,\c!corner,\c!color,\c!screen] \copyparameters [\??ma\v!rightpage\c!background][\??ma\v!rightpage] [\c!offset,\c!depth,\c!radius,\c!corner,\c!color,\c!screen] %D We save some keying by defining the areas using %D intermediate commands. The inheritance macro makes sure %D that copies are efficient. \def\dodocommand#1#2% {\copylocalframed [\??ma#1#2][\??ma\v!page]% \getparameters [\??ma#1#2] [\c!background=,\c!frame=,\c!color=,\c!screen=\@@rsscreen, \c!bottomframe=,\c!topframe=,\c!leftframe=,\c!rightframe=]% \inheritparameter[\??ma][#1#2\c!color][\v!page\c!color]% \inheritparameter[\??ma][#1#2\c!screen][\v!page\c!screen]% \inheritparameter[\??ma][#1#2\c!framecolor][\v!page\c!framecolor]% \inheritparameter[\??ma][#1#2\c!backgroundcolor][\v!page\c!backgroundcolor]% \inheritparameter[\??ma][#1#2\c!backgroundscreen][\v!page\c!backgroundscreen]} %D The stand alone text area inherits from the page too. \dodocommand\v!text \empty \dodocommand\v!hidden\empty %D We now define all 25 main areas in a row. \def\docommand#1% {\dodocommand#1\v!leftedge \dodocommand#1\v!leftmargin \dodocommand#1\v!text \dodocommand#1\v!rightmargin \dodocommand#1\v!rightedge} \docommand\v!top \docommand\v!header \docommand\v!text \docommand\v!footer \docommand\v!bottom %D We need some cleanup now. \let\dodocommand\relax \let\docommand\relax %D We now set up the individual areas to use reasonable %D defaults. \setupbackgrounds [\c!state=\c!start] \setupbackgrounds [\v!paper,\v!page,\v!leftpage,\v!rightpage] [\c!frame=\v!off, \c!radius=.5\bodyfontsize, \c!corner=\v!rectangular, \c!background=, \c!screen=\@@rsscreen, \c!color=, %\c!frameoffset=\getvalue{\??ma\v!page\c!offset}, %\c!backgroundoffset=\getvalue{\??ma\v!page\c!offset}, \c!offset=\!!zeropoint, % later set to \v!overlay, watch out ! \c!depth=\!!zeropoint] \def\docommand#1% {\inheritparameter[\??ma][#1\c!frameoffset][\v!page\c!offset]% \inheritparameter[\??ma][#1\c!backgroundoffset][\v!page\c!offset]} \docommand\v!paper \docommand\v!page \docommand\v!leftpage \docommand\v!rightpage %D Again we clean up temporary macros. \let\docommand\relax %D The hidden layer can be populated by extending the %D following comma separated list. This only happens in core %D modules. % todo page-2 .. page+2 achter pagina -> bleed % spread-2 .. spread+2 achter spread -> spread (repeat 2 times) \def\enablehiddenbackground {\global\settrue\hiddenbackgroundenabled \global\somebackgroundtrue \recalculatebackgrounds} \def\disablehiddenbackground {\global\setfalse\hiddenbackgroundenabled} \def\hiddenbackground {\v!text-2,\v!text-1,\v!foreground,\v!text+1,\v!text+2} \setupbackgrounds [\v!hidden] [\c!background=\hiddenbackground] % The next series is used in local (for instance floating) % backgrounds. \presetlocalframed [\??ma\v!local] \def\localbackground {\v!local-2,\v!local-1,\v!foreground,\v!local+1,\v!local+2} \defineoverlay[\v!local-2][\positionoverlay{\v!local-2}] \defineoverlay[\v!local-1][\positionoverlay{\v!local-1}] \defineoverlay[\v!local+1][\positionoverlay{\v!local+1}] \defineoverlay[\v!local+2][\positionoverlay{\v!local+2}] \def\addlocalbackgroundtobox {\ifconditional\hiddenbackgroundenabled \expandafter\doaddlocalbackground \else \resetglobal \expandafter\gobbleoneargument \fi} \def\doaddlocalbackground#1% {\dodoglobal\setbox#1\hbox {\fastlocalframed % \localframed [\??ma\v!local] [\c!component=local,\c!frame=\v!off,\c!offset=\v!overlay,\c!setups=,% \c!location=\v!keep,% when we use \localframed instead of \fastlocalframed \c!background=\localbackground]% {\registerMPlocaltextarea{\box#1}}}% \resetglobal % redundant \doglobal\increment\localpositionnumber\relax} % afterwards ! % Test how previous macro behaves with depth: % % \startcolumnset % \input tufte % \placefigure{none}{\framed[lines=5]{xxx}} % \input tufte % \placefigure{none}{\starttabulate\NC test\nc test\NC\NR\stoptabulate} % \input tufte % \stopcolumnset %D Because we haven't really set up backgrounds yet, we set %D the main efficiency switch to false. \somebackgroundfalse \protect \endinput %D Removed \quote {features}: %D %D \starttyping %D \startinteraction %D \doifmarginswapelse %D {\copy\leftbackground} %D {\copy\rightbackground}% %D \stopinteraction %D \stoptyping %D %D \starttyping %D \edef\setpagebackgrounddepth% %D {\dp#2=\the\dp#2}% %D \setbox#2=\vbox\localframed[\??ma#1]{...} %D \setpagebackgrounddepth %D \stoptyping