page-bck.mkii / last modification: 2020-01-30 14:15
%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  <box>
%D \addtextbackground  <box>
%D \addpagebackground  <box>
%D \addprintbackground <box>
%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